add multiple authorizor fallback methods

This commit is contained in:
Jonathan Shook 2022-07-05 21:12:28 -05:00
parent a0c116bfa0
commit 36c852f6ec
3 changed files with 107 additions and 41 deletions

View File

@ -1,4 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2022 nosqlbench
~
~ Licensed 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

View File

@ -1,4 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2022 nosqlbench
~
~ Licensed 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>nosqlbench</artifactId>

View File

@ -20,8 +20,15 @@ import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import io.nosqlbench.engine.clients.grafana.annotator.GrafanaMetricsAnnotator;
import io.nosqlbench.engine.clients.grafana.authorizers.CurlCmdInjector;
import io.nosqlbench.engine.clients.grafana.authorizers.RawSocketInjector;
import io.nosqlbench.engine.clients.grafana.transfer.*;
import io.nosqlbench.engine.clients.prometheus.*;
import io.nosqlbench.engine.clients.prometheus.PMatrixData;
import io.nosqlbench.engine.clients.prometheus.PromQueryResult;
import io.nosqlbench.engine.clients.prometheus.PromSeriesLookupResult;
import io.nosqlbench.nb.api.NBEnvironment;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.File;
import java.lang.reflect.Type;
@ -43,6 +50,7 @@ import java.util.regex.Pattern;
*/
public class GrafanaClient {
private final static Logger logger = LogManager.getLogger(GrafanaClient.class);
private static final Gson gson = new GsonBuilder().setPrettyPrinting().create();
private final GrafanaClientConfig config;
private List<GDataSource> datasources;
@ -194,7 +202,8 @@ public class GrafanaClient {
HttpResponse<String> response = null;
try {
response = client.send(rqb.build(), HttpResponse.BodyHandlers.ofString());
HttpRequest request = rqb.build();
response = client.send(request, HttpResponse.BodyHandlers.ofString());
} catch (Exception e) {
if (e.getMessage().contains("WWW-Authenticate header missing")) {
throw new RuntimeException("Java HttpClient was not authorized, and it saw no WWW-Authenticate header" +
@ -504,11 +513,22 @@ public class GrafanaClient {
public ApiToken createApiToken(String name, String role, long ttl) {
ApiTokenRequest r = new ApiTokenRequest(name, role, ttl);
ApiToken token = postApiTokenRequest(r, ApiToken.class, "gen api token");
return token;
Optional<ApiToken> token = postApiTokenRequest(r, "gen api token");
if (token.isPresent()) {
logger.info("authorized grafana client via built-in authorizer");
return token.get();
} else {
Path path = NBEnvironment.INSTANCE
.interpolate("$NBSTATEDIR/grafana/grafana.db")
.or(() -> Optional.of("~/.nosqlbench/grafana/grafana_apikey"))
.map(Path::of).orElseThrow();
throw new RuntimeException("Unable to authorize local grafana client with any" +
" built in local authorizer. Please store a grafana API key at:\n" + path
+ "\n and start again.");
}
}
private <T> T postApiTokenRequest(Object request, Class<? extends T> clazz, String desc) {
private Optional<ApiToken> postApiTokenRequest(Object request, String desc) {
HttpRequest rq = config.newJsonPOST("api/auth/keys", request);
HttpClient client = config.newClient();
@ -517,19 +537,33 @@ public class GrafanaClient {
response = client.send(rq, HttpResponse.BodyHandlers.ofString());
} catch (Exception e) {
if (e.getMessage() != null && e.getMessage().contains("WWW-Authenticate header missing")) {
throw new RuntimeException("Java HttpClient was not authorized, and it saw no WWW-Authenticate header" +
" in the response, so this is probably Grafana telling you that the auth scheme failed. Normally " +
"this error would be thrown by Java HttpClient:" + e.getMessage());
try {
Optional<ApiToken> token = Optional.empty();
if (request instanceof ApiTokenRequest apirq) {
token = RawSocketInjector.submit(apirq, rq);
if (token.isPresent()) {
return token;
}
token = CurlCmdInjector.submit(apirq, rq);
if (token.isPresent()) {
return token;
}
}
} catch (Exception e2) {
logger.error("Error while using secondary method to init grafana client key after auth failure: " + e2, e2);
throw e2;
}
}
throw new RuntimeException(e);
}
if (response.statusCode() < 200 || response.statusCode() >= 300) {
throw new RuntimeException("Request to grafana failed with status code " + response.statusCode() + "\n" +
" while trying to '" + desc + "'\n at baseuri " + config.getBaseUri() + ": " + response.body());
}
String body = response.body();
T result = gson.fromJson(body, clazz);
return result;
ApiToken result = gson.fromJson(body, ApiToken.class);
return Optional.ofNullable(result);
}
public <T> T doProxyQuery(String dsname, String path, String query, TypeToken<? extends T> asType) {