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

Support OAuth2 authorization flow #476

Merged
merged 2 commits into from
Feb 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

<rabbitmq.version>5.16.0</rabbitmq.version>
<jackson.version>2.14.1</jackson.version>
<slf4j.version>2.0.6</slf4j.version>
<commons-cli.version>1.5.0</commons-cli.version>
<metrics.version>4.2.15</metrics.version>
Expand Down Expand Up @@ -112,6 +113,11 @@
<artifactId>amqp-client</artifactId>
<version>${rabbitmq.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
Expand Down
25 changes: 25 additions & 0 deletions src/docs/asciidoc/usage-advanced.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,31 @@ Here is how to run PerfTest with a certificate/key pair generated by the aforeme
-Djavax.net.ssl.keyStoreType=PKCS12 \
-jar perf-test.jar -h amqps://localhost:5671

== OAuth2 authentication/authorization

It's possible to connect to a RabbitMQ instance configured to use
https://www.rabbitmq.com/oauth2.html[OAuth 2.0 Authentication
Backend]. In this case it is not necessary to provide a username and a
password in the AMQP URI: a token endpoint URI, client id and
client secret should be provided as separate command line options instead.
All 3 should be specified at once.

Here is an example:

java -jar perf-test.jar \
--uri amqps://some-uri-without-user-and-password:5671 \
--oauth2-token-endpoint https://example.com/api/auth/token \
--oauth2-client-id 12345 \
--oauth2-client-secret qwerty \
--oauth2-grant-type client_credentials \
--oauth2-parameters orgId=1212 \
--oauth2-parameters subject_token_type=urn:ietf:params:oauth:token-type:access_token

`--oauth2-grant-type` is optional and defaults to `client_credential`.

Any number of optional parameters can be passed to the token endpoint via
the `--oauth2-parameters` option.

== Using Environment Variables as Options

Environment variables can sometimes be easier to work with than command line options, for example
Expand Down
58 changes: 58 additions & 0 deletions src/main/java/com/rabbitmq/perf/PerfTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@
import com.rabbitmq.client.ExceptionHandler;
import com.rabbitmq.client.RecoveryDelayHandler;
import com.rabbitmq.client.impl.ClientVersion;
import com.rabbitmq.client.impl.CredentialsProvider;
import com.rabbitmq.client.impl.CredentialsRefreshService;
import com.rabbitmq.client.impl.DefaultExceptionHandler;
import com.rabbitmq.client.impl.OAuth2ClientCredentialsGrantCredentialsProvider.OAuth2ClientCredentialsGrantCredentialsProviderBuilder;
import com.rabbitmq.client.impl.DefaultCredentialsRefreshService.DefaultCredentialsRefreshServiceBuilder;
import com.rabbitmq.client.impl.nio.NioParams;
import com.rabbitmq.perf.Metrics.ConfigurationContext;
import com.rabbitmq.perf.metrics.CompositeMetricsFormatter;
Expand Down Expand Up @@ -168,6 +172,48 @@ public static void main(String [] args, PerfTestOptions perfTestOptions) {
shutdownService.wrap(() -> nioExecutor.shutdownNow());
}

String oauth2TokenEndpoint = strArg(cmd, "o2uri", null);
if (oauth2TokenEndpoint != null) {
OAuth2ClientCredentialsGrantCredentialsProviderBuilder builder =
new OAuth2ClientCredentialsGrantCredentialsProviderBuilder();
builder.tokenEndpointUri(oauth2TokenEndpoint);

String clientId = strArg(cmd, "o2id", null);
if (clientId == null) {
throw new MissingArgumentException("-o2id/--oauth2-client-id is mandatory when OAuth2 is used");
}
builder.clientId(clientId);

String clientSecret = strArg(cmd, "o2sec", null);
if (clientSecret == null) {
throw new MissingArgumentException("-o2sec/--oauth2-client-secret is mandatory when OAuth2 is used");
}
builder.clientSecret(clientSecret);

String grantType = strArg(cmd, "o2gr", "client_credentials");
builder.grantType(grantType);

List<String> parameters = lstArg(cmd, "o2p");
for (String param : parameters) {
String[] keyValue = param.split("=",2);
builder.parameter(keyValue[0], keyValue[1]);
}

if (oauth2TokenEndpoint.toLowerCase().startsWith("https")) {
if (sslContext == null) {
builder.tls().dev();
} else {
builder.tls().sslContext(sslContext);
}
}

CredentialsProvider credentialsProvider = builder.build();
factory.setCredentialsProvider(credentialsProvider);

CredentialsRefreshService refreshService = new DefaultCredentialsRefreshServiceBuilder().build();
factory.setCredentialsRefreshService(refreshService);
}

factory.setSocketConfigurator(Utils.socketConfigurator(cmd));
if (factory.getNioParams() != null) {
factory.getNioParams().setSslEngineConfigurator(Utils.sslEngineConfigurator(cmd));
Expand Down Expand Up @@ -936,6 +982,18 @@ static Options getOptions() {
+ "instance synchronization"));
options.addOption(new Option("ist", "instance-sync-timeout", true, "Instance synchronization time "
+ "in seconds. Default is 600 seconds."));

options.addOption(new Option("o2uri","oauth2-token-endpoint", true, "OAuth2 token endpoint URI. "
+ "At least --oauth2-client-id and --oauth2-client-secret should be also specified for OAuth2 flow to work."));
options.addOption(new Option("o2id", "oauth2-client-id", true, "OAuth2 client id"));
options.addOption(new Option("o2sec", "oauth2-client-secret", true, "OAuth2 client secret"));
options.addOption(new Option("o2gr", "oauth2-grant-type", true, "OAuth2 grant type. "
+ "Default is 'client_credential'"));
Option oauth2ParamsOption = new Option("o2p", "oauth2-parameters",true, "Additional parameters for OAuth2 "
+ "token endpoint, e.g. orgId=1234. Can be specified multiple times.");
oauth2ParamsOption.setArgs(Option.UNLIMITED_VALUES);
options.addOption(oauth2ParamsOption);

return options;
}

Expand Down