Skip to content

Commit c5a7b05

Browse files
authored
Improve AuthenticationProviderBasic metrics (#1350)
1 parent b358339 commit c5a7b05

File tree

2 files changed

+42
-6
lines changed

2 files changed

+42
-6
lines changed

amqp-impl/src/main/java/io/streamnative/pulsar/handlers/amqp/authentication/AuthenticationProviderBasic.java

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,28 @@ public class AuthenticationProviderBasic implements AuthenticationProvider {
4040
private static final String HTTP_HEADER_NAME = "Authorization";
4141
private Map<String, String> users;
4242

43+
AuthenticationMetrics metrics;
44+
45+
private enum ErrorCode {
46+
UNKNOWN,
47+
EMPTY_AUTH_DATA,
48+
INVALID_HEADER,
49+
INVALID_AUTH_DATA,
50+
INVALID_TOKEN,
51+
}
52+
4353
@SneakyThrows
4454
@Override
4555
public void initialize(ServiceConfiguration config) {
46-
String basicAuthConf = (String) config.getProperty("basicAuthConf");
56+
initialize(Context.builder().config(config).build());
57+
}
58+
59+
@SneakyThrows
60+
@Override
61+
public void initialize(Context context) throws IOException {
62+
metrics = new AuthenticationMetrics(context.getOpenTelemetry(),
63+
getClass().getSimpleName(), getAuthMethodName());
64+
String basicAuthConf = (String) context.getConfig().getProperty("basicAuthConf");
4765

4866
byte[] data;
4967
boolean isFile = basicAuthConf.startsWith("file:");
@@ -79,8 +97,10 @@ public String authenticate(AuthenticationDataSource authData) throws Authenticat
7997
String password = authParams.getPassword();
8098
String msg = "Unknown user or invalid password";
8199

100+
ErrorCode errorCode = ErrorCode.UNKNOWN;
82101
try {
83102
if (users.get(userId) == null) {
103+
errorCode = ErrorCode.EMPTY_AUTH_DATA;
84104
throw new AuthenticationException(msg);
85105
}
86106

@@ -92,19 +112,20 @@ public String authenticate(AuthenticationDataSource authData) throws Authenticat
92112
if (splitEncryptedPassword.size() != 4 || !encryptedPassword
93113
.equals(Md5Crypt.apr1Crypt(password.getBytes(StandardCharsets.UTF_8),
94114
splitEncryptedPassword.get(2)))) {
115+
errorCode = ErrorCode.INVALID_TOKEN;
95116
throw new AuthenticationException(msg);
96117
}
97118
// For crypt algorithm
98119
} else if (!encryptedPassword.equals(Crypt.crypt(password.getBytes(StandardCharsets.UTF_8),
99120
encryptedPassword.substring(0, 2)))) {
121+
errorCode = ErrorCode.INVALID_TOKEN;
100122
throw new AuthenticationException(msg);
101123
}
102124
} catch (AuthenticationException exception) {
103-
AuthenticationMetrics.authenticateFailure(getClass().getSimpleName(), getAuthMethodName(),
104-
exception.getMessage());
125+
incrementFailureMetric(errorCode);
105126
throw exception;
106127
}
107-
AuthenticationMetrics.authenticateSuccess(getClass().getSimpleName(), getAuthMethodName());
128+
metrics.recordSuccess();
108129
return userId;
109130
}
110131

@@ -113,7 +134,7 @@ public void close() throws IOException {
113134
// noop
114135
}
115136

116-
private static class AuthParams {
137+
private class AuthParams {
117138
private final String userId;
118139
private final String password;
119140

@@ -125,25 +146,30 @@ public AuthParams(AuthenticationDataSource authData) throws AuthenticationExcept
125146
String rawAuthToken = authData.getHttpHeader(HTTP_HEADER_NAME);
126147
// parsing and validation
127148
if (StringUtils.isBlank(rawAuthToken) || !rawAuthToken.toUpperCase().startsWith("BASIC ")) {
149+
incrementFailureMetric(ErrorCode.INVALID_HEADER);
128150
throw new AuthenticationException("Authentication token has to be started with \"Basic \"");
129151
}
130152
String[] splitRawAuthToken = rawAuthToken.split(" ");
131153
if (splitRawAuthToken.length != 2) {
154+
incrementFailureMetric(ErrorCode.INVALID_HEADER);
132155
throw new AuthenticationException("Base64 encoded token is not found");
133156
}
134157

135158
try {
136159
authParams = new String(java.util.Base64.getDecoder().decode(splitRawAuthToken[1]),
137160
StandardCharsets.UTF_8);
138161
} catch (Exception e) {
162+
incrementFailureMetric(ErrorCode.INVALID_HEADER);
139163
throw new AuthenticationException("Base64 decoding is failure: " + e.getMessage());
140164
}
141165
} else {
166+
incrementFailureMetric(ErrorCode.EMPTY_AUTH_DATA);
142167
throw new AuthenticationException("Authentication data source does not have data");
143168
}
144169

145170
String[] parsedAuthParams = authParams.split(":");
146171
if (parsedAuthParams.length != 2) {
172+
incrementFailureMetric(ErrorCode.INVALID_AUTH_DATA);
147173
throw new AuthenticationException("Base64 decoded params are invalid");
148174
}
149175

@@ -159,4 +185,10 @@ public String getPassword() {
159185
return password;
160186
}
161187
}
188+
189+
@Override
190+
public void incrementFailureMetric(Enum<?> errorCode) {
191+
metrics.recordFailure(errorCode);
192+
}
193+
162194
}

pom.xml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
<project.compiler.release>${maven.compiler.target}</project.compiler.release>
4141

4242
<!-- dependencies -->
43-
<pulsar.version>3.4.0-SNAPSHOT</pulsar.version>
43+
<pulsar.version>4.0.0-ursa-4-SNAPSHOT</pulsar.version>
4444
<qpid-protocol-plugin.version>8.0.0</qpid-protocol-plugin.version>
4545
<rabbitmq.version>5.8.0</rabbitmq.version>
4646

@@ -384,6 +384,10 @@
384384
<id>nexus-snapshot-repo</id>
385385
<url>https://s01.oss.sonatype.org/content/repositories/snapshots</url>
386386
</repository>
387+
<repository>
388+
<id>ossrh</id>
389+
<url>https://s01.oss.sonatype.org/service/local/repositories/0/content</url>
390+
</repository>
387391
</repositories>
388392

389393
</project>

0 commit comments

Comments
 (0)