blob: fef420a02f92265e370de962ebfcf0eac436ae22 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jena.http;
import static org.apache.jena.fuseki.test.HttpTest.expect401;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import org.apache.jena.graph.Graph;
import org.apache.jena.graph.Triple;
import org.apache.jena.http.sys.HttpRequestModifier;
import org.apache.jena.http.sys.RegistryRequestModifier;
import org.apache.jena.query.ARQ;
import org.apache.jena.rdflink.RDFLink;
import org.apache.jena.rdflink.RDFLinkFactory;
import org.apache.jena.rdflink.RDFLinkHTTP;
import org.apache.jena.riot.web.HttpNames;
import org.apache.jena.sparql.core.DatasetGraph;
import org.apache.jena.sparql.core.DatasetGraphFactory;
import org.apache.jena.sparql.exec.QueryExec;
import org.apache.jena.sparql.exec.http.DSP;
import org.apache.jena.sparql.exec.http.GSP;
import org.apache.jena.sparql.exec.http.QueryExecHTTP;
import org.apache.jena.sparql.exec.http.UpdateExecHTTP;
import org.apache.jena.sparql.graph.GraphFactory;
import org.apache.jena.sparql.sse.SSE;
import org.apache.jena.test.conn.EnvTest;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/**
* This is more than just RDFLinkRemote - it covers the components
*/
public class TestAuthRemote {
private static String user = "user";
private static String password = "password";
private EnvTest env;
@Before public void beforeClass() {
//FusekiLogging.setLogging();
env = EnvTest.createAuth("/ds", DatasetGraphFactory.createTxnMem(), user, password);
}
@After public void after() {
EnvTest.stop(env);
}
// ---- QueryExecHTTP
@Test
public void auth_qe_no_auth() {
expect401(()->{
try ( QueryExec qexec = QueryExecHTTP.newBuilder()
//.httpClient(hc)
.endpoint(env.datasetURL())
.queryString("ASK{}")
.build()) {
qexec.ask();
}
});
}
@Test
public void auth_qe_good_auth() {
try ( QueryExec qexec = QueryExecHTTP.newBuilder()
.httpClient(env.httpClientAuthGood())
.endpoint(env.datasetURL())
.queryString("ASK{}")
.build()) {
qexec.ask();
}
}
@Test
public void auth_qe_bad_auth() {
expect401(()->{
try ( QueryExec qexec = QueryExecHTTP.newBuilder()
.httpClient(env.httpClientAuthBad())
.endpoint(env.datasetURL())
.queryString("ASK{}")
.build()) {
qexec.ask();
}
});
}
// Retries up to "java.net.httpclient.redirects.retrylimit" (3 by default).
@Test
public void auth_qe_bad_auth_retries() {
expect401(()->{
try ( QueryExec qexec = QueryExecHTTP.newBuilder()
// retry blindly.
.httpClient(EnvTest.httpClient(env.authenticatorBadRetries()))
.endpoint(env.datasetURL())
.queryString("ASK{}")
.build()) {
qexec.ask();
}
});
}
// ---- UpdateExecHTTP
@Test
public void auth_update_no_auth() {
expect401(()->
UpdateExecHTTP.newBuilder()
.endpoint(env.datasetURL())
.updateString("INSERT DATA { <x:s> <x:p> <x:o> }")
.build()
.execute()
);
}
@Test
public void auth_update_good_auth() {
UpdateExecHTTP.newBuilder()
.httpClient(env.httpClientAuthGood())
.endpoint(env.datasetURL())
.updateString("INSERT DATA { <x:s> <x:p> <x:o> }")
.build()
.execute();
}
@Test
public void auth_update_bad_auth() {
expect401(()->
UpdateExecHTTP.newBuilder()
.httpClient(env.httpClientAuthBad())
.endpoint(env.datasetURL())
.updateString("INSERT DATA { <x:s> <x:p> <x:o> }")
.build()
.execute()
);
}
// ---- GSP
@Test
public void auth_gsp_no_auth() {
expect401(()->{
GSP.service(env.datasetURL()).defaultGraph().GET();
});
}
@Test
public void auth_gsp_good_auth_1() {
Graph graph = GSP.service(env.datasetURL()).httpClient(env.httpClientAuthGood()).defaultGraph().GET();
assertNotNull(graph);
}
@Test
public void auth_dsp_good_auth_2() {
DatasetGraph dsg = DSP.service(env.datasetURL()).httpClient(env.httpClientAuthGood()).GET();
assertNotNull(dsg);
}
@Test
public void auth_dsp_good_auth_3() {
DatasetGraph dsg = DSP.service(env.datasetURL()).httpClient(env.httpClientAuthGood()).GET();
assertNotNull(dsg);
}
@Test
public void auth_gsp_bad_auth_1() {
// 401 because we didn't authenticate.
expect401(()->
GSP.service(env.datasetURL()).httpClient(env.httpClientAuthBad()).defaultGraph().GET()
);
}
@Test
public void auth_dsp_bad_auth_2() {
// 401 because we didn't authenticate.
expect401(()->
DSP.service(env.datasetURL()).httpClient(env.httpClientAuthBad()).GET()
);
}
@Test
public void auth_dsp_bad_auth_3() {
// 401 because we didn't authenticate.
expect401(()->
DSP.service(env.datasetURL()).httpClient(env.httpClientAuthBad()).GET()
);
}
// RDFLink
@Test
public void auth_link_no_auth_1() {
expect401(()->{
try ( RDFLink link = RDFLinkFactory.connect(env.datasetURL()) ) {
link.queryAsk("ASK{}");
}
});
}
@Test
public void auth_link_no_auth_2() {
expect401(()->{
try ( RDFLink link = RDFLinkFactory.connect(env.datasetURL()) ) {
link.update("INSERT DATA { <x:s> <x:p> <x:o> }");
}
});
}
@Test
public void auth_link_no_auth_3() {
expect401(()->{
try ( RDFLink link = RDFLinkFactory.connect(env.datasetURL()) ) {
link.get();
}
});
}
@Test
public void auth_link_good_auth_1() {
try ( RDFLink link = RDFLinkHTTP.newBuilder()
.destination(env.datasetURL())
.httpClient(env.httpClientAuthGood())
.build()) {
link.queryAsk("ASK{}");
link.update("INSERT DATA { <x:s> <x:p> <x:o> }");
Graph graph = link.get();
assertNotNull(graph);
DatasetGraph dsg = link.getDataset();
assertNotNull(dsg);
}
}
@Test
public void auth_link_bad_auth_1() {
// 401 (not 403) because we didn't authenticate
// 403 is recognized authenticate, not sufficient for ths resource.
expect401(()->{
try ( RDFLink link = RDFLinkHTTP.newBuilder()
.destination(env.datasetURL())
.httpClient(env.httpClientAuthBad())
.build()) {
link.queryAsk("ASK{}");
}
});
}
@Test
public void auth_link_bad_auth_2() {
// 401 (not 403) because we didn't authenticate
expect401(()->{
try ( RDFLink link = RDFLinkHTTP.newBuilder()
.destination(env.datasetURL())
.httpClient(env.httpClientAuthBad())
.build()) {
link.update("INSERT DATA { <x:s> <x:p> <x:o> }");
}
});
}
@Test
public void auth_link_bad_auth_3() {
// 401 (not 403) because we didn't authenticate
expect401(()->{
try ( RDFLink link = RDFLinkHTTP.newBuilder()
.destination(env.datasetURL())
.httpClient(env.httpClientAuthBad())
.build()) {
link.get();
}
});
}
// RegistryHttpClient
private void exec_auth_registry_exact(String key) {
RegistryHttpClient.get().add(key, env.httpClientAuthGood());
try { exec_register_test(); }
finally { RegistryHttpClient.get().clear(); }
}
private void exec_auth_registry_prefix(String key) {
RegistryHttpClient.get().addPrefix(key, env.httpClientAuthGood());
try { exec_register_test(); }
finally { RegistryHttpClient.get().clear(); }
}
private void exec_register_test() {
try (QueryExec qExec = QueryExecHTTP.newBuilder()
.endpoint(env.datasetURL())
.queryString("ASK{ }")
.build()) {
boolean b = qExec.ask();
assertTrue(b);
}
}
@Test
public void auth_registryHttpClient_exact_1() {
exec_auth_registry_exact(env.datasetURL());
}
@Test
public void auth_registryHttpClient_exact_2() {
// Use prefix match for server-wide
expect401(()->{
exec_auth_registry_exact(env.serverBaseURL());
});
}
@Test
public void auth_registryHttpClient_exact_401_1() {
expect401(()->{
exec_auth_registry_exact("Junk");
});
}
@Test
public void auth_registryHttpClient_exact_401_2() {
// Longer name, child
String registerKey = env.serverPath(env.dsName()+"/XYZ");
expect401(()->{
exec_auth_registry_exact(registerKey);
});
}
@Test
public void auth_registryHttpClient_exact_401_3() {
// Longer name.
// It does not match; prefixes are limited to ending in "/"
String registerKey = env.serverPath(env.dsName()+"X");
expect401(()->{
exec_auth_registry_exact(registerKey);
});
}
@Test
public void auth_registryHttpClient_exact_401_4() {
// Different dataset
String registerKey = env.serverPath("ABC");
expect401(()->{
exec_auth_registry_exact(registerKey);
});
}
@Test
public void auth_registryHttpClient_exact_401_5() {
// Shorter dataset name, prefix of actual one.
// It does not match.
String registerKey = env.serverPath("d");
expect401(()->{
exec_auth_registry_exact(registerKey);
});
}
@Test(expected=IllegalArgumentException.class)
public void auth_registryHttpClient_prefix_1() {
// Should use exact
exec_auth_registry_prefix(env.datasetURL());
}
@Test
public void auth_registryHttpClient_prefix_2() {
// Everything at a server. Must end in "/"
exec_auth_registry_prefix(env.serverBaseURL());
}
@Test
public void auth_registryHttpClient_prefix_401_1() {
expect401(()->{
exec_auth_registry_prefix("Junk/");
});
}
@Test
public void auth_registryHttpClient_prefix_401_2() {
// Longer name.
String registerKey = env.serverPath(env.dsName()+"/");
expect401(()->{
exec_auth_registry_prefix(registerKey);
});
}
@Test
public void auth_registryHttpClient_prefix_401_3() {
// Longer name.
String registerKey = env.serverPath(env.dsName()+"/xyz/");
expect401(()->{
exec_auth_registry_prefix(registerKey);
});
}
@Test
public void auth_registryHttpClient_prefix_401_4() {
// Different dataset
String registerKey = env.serverPath("A/");
expect401(()->{
exec_auth_registry_prefix(registerKey);
});
}
@Test(expected=IllegalArgumentException.class)
public void auth_registryHttpClient_prefix_401_5() {
// Not cause 401. Shorter dataset name, prefix of actual one.
String registerKey = env.serverPath("d");
exec_auth_registry_prefix(registerKey);
}
// Other ways of setting auth.
// Using HttpClient is preferred but the basic operations can use
// ServiceTuning or directly supply the headers.
// ServiceTuning
@Test
public void auth_service_tuning_1_RegistryRequestModifier() {
// using RegistryRequestModifier
HttpRequestModifier mods = (params, headers) -> headers.put(HttpNames.hAuthorization, HttpLib.basicAuth(user, password));
RegistryRequestModifier svcReg = new RegistryRequestModifier();
svcReg.add(env.datasetURL(), mods);
ARQ.getContext().put(ARQ.httpRegistryRequestModifer, svcReg);
try {
// Component level
UpdateExecHTTP.newBuilder()
.endpoint(env.datasetURL())
.updateString("INSERT DATA { <x:s> <x:p> <x:o> }")
.build()
.execute();
try ( QueryExec qExec = QueryExecHTTP.newBuilder()
.endpoint(env.datasetURL())
.queryString("ASK{ <x:s> <x:p> <x:o> }")
.build()){
boolean b = qExec.ask();
assertTrue(b);
}
} finally {
// clear up
ARQ.getContext().remove(ARQ.httpRegistryRequestModifer);
}
}
@Test
public void auth_service_tuning_2_HttpRequestModifer() {
// As HttpRequestModifer
HttpRequestModifier mods = (params, headers) -> headers.put(HttpNames.hAuthorization, HttpLib.basicAuth(user, password));
ARQ.getContext().put(ARQ.httpRequestModifer, mods);
try {
try ( RDFLink link = RDFLinkHTTP.newBuilder()
.destination(env.datasetURL())
.build()) {
link.update("INSERT DATA { <x:s> <x:p> <x:z> }");
boolean b = link.queryAsk("ASK{ <x:s> <x:p> <x:z> }");
assertTrue(b);
}
} finally {
// clear up
ARQ.getContext().remove(ARQ.httpRequestModifer);
}
}
@Test
public void auth_header_1() {
Triple triple = SSE.parseTriple("(<x:s> <x:p> <x:o>)");
Graph graph = GraphFactory.createDefaultGraph();
graph.add(triple);
GSP.service(env.datasetURL())
.httpHeader(HttpNames.hAuthorization, HttpLib.basicAuth(user, password))
.defaultGraph()
.POST(graph);
// By query.
try ( QueryExec qExec = QueryExecHTTP.newBuilder()
.endpoint(env.datasetURL())
.queryString("ASK{ <x:s> <x:p> <x:o> }")
.httpHeader(HttpNames.hAuthorization, HttpLib.basicAuth(user, password))
.build()) {
boolean b = qExec.ask();
assertTrue(b);
}
// By GSP
Graph graph2 =
GSP.service(env.datasetURL())
.httpHeader(HttpNames.hAuthorization, HttpLib.basicAuth(user, password))
.defaultGraph()
.GET();
assertTrue(graph.isIsomorphicWith(graph2));
}
}