diff --git a/conf/functions_worker.yml b/conf/functions_worker.yml
index b41ac8f37a44f..bb15e0ca416da 100644
--- a/conf/functions_worker.yml
+++ b/conf/functions_worker.yml
@@ -311,6 +311,8 @@ authenticationProviders:
authorizationProvider: org.apache.pulsar.broker.authorization.PulsarAuthorizationProvider
# Set of role names that are treated as "super-user", meaning they will be able to access any admin-api
superUserRoles:
+# Set of role names that are treated as "proxy" roles. These are the roles that can supply the originalPrincipal.
+proxyRoles:
#### tls configuration for worker service
# Enable TLS
diff --git a/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authentication/AuthenticationParameters.java b/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authentication/AuthenticationParameters.java
new file mode 100644
index 0000000000000..638772345bdf3
--- /dev/null
+++ b/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authentication/AuthenticationParameters.java
@@ -0,0 +1,67 @@
+/*
+ * 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.pulsar.broker.authentication;
+
+import lombok.Builder;
+
+/**
+ * A class to collect all the common fields used for authentication. Because the authentication data source is
+ * not always consistent when using the Pulsar Protocol and the Pulsar Proxy
+ * (see 19332), this class is currently restricted
+ * to use only in authenticating HTTP requests.
+ */
+@Builder
+@lombok.Value
+public class AuthenticationParameters {
+
+ /**
+ * The original principal (or role) of the client.
+ *
+ * For HTTP Authentication, there are two possibilities. When the client connects directly to the broker, this
+ * field is null (assuming the client hasn't supplied the original principal header). When the client connects
+ * through the proxy, the proxy calculates the original principal based on the client's authentication data and
+ * supplies it in this field.
+ *
+ */
+ String originalPrincipal;
+
+ /**
+ * The client role.
+ *
+ * For HTTP Authentication, there are three possibilities. When the client connects directly to the broker, this
+ * is the client's role. When the client connects through the proxy using mTLS, this is the role of the proxy.
+ * In this case, the {@link #originalPrincipal} is also supplied and is the role of the original client as
+ * determined by the proxy. When the client connects through the proxy using any other form of authentication,
+ * this is the role of the original client. In this case, the {@link #originalPrincipal} is also the role of
+ * the original client.
+ *
+ */
+ String clientRole;
+
+ /**
+ * The authentication data source used to generate the {@link #clientRole}.
+ *
+ * For HTTP Authentication, there are three possibilities. When the client connects directly to the broker, this
+ * is the client's {@link AuthenticationDataSource}. When the client connects through the proxy using mTLS, this
+ * is the proxy's {@link AuthenticationDataSource}. When the client connects through the proxy using any other
+ * form of authentication, this is the original client's {@link AuthenticationDataSource}.
+ *
+ */
+ AuthenticationDataSource clientAuthenticationDataSource;
+}
diff --git a/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authorization/AuthorizationService.java b/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authorization/AuthorizationService.java
index 6fff04b33b618..6c730f20092dd 100644
--- a/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authorization/AuthorizationService.java
+++ b/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authorization/AuthorizationService.java
@@ -23,10 +23,12 @@
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
+import javax.ws.rs.core.Response;
import org.apache.commons.lang3.StringUtils;
import org.apache.pulsar.broker.PulsarServerException;
import org.apache.pulsar.broker.ServiceConfiguration;
import org.apache.pulsar.broker.authentication.AuthenticationDataSource;
+import org.apache.pulsar.broker.authentication.AuthenticationParameters;
import org.apache.pulsar.broker.resources.PulsarResources;
import org.apache.pulsar.common.naming.NamespaceName;
import org.apache.pulsar.common.naming.TopicName;
@@ -49,6 +51,7 @@
public class AuthorizationService {
private static final Logger log = LoggerFactory.getLogger(AuthorizationService.class);
+ private final PulsarResources resources;
private final AuthorizationProvider provider;
private final ServiceConfiguration conf;
@@ -61,6 +64,7 @@ public AuthorizationService(ServiceConfiguration conf, PulsarResources pulsarRes
provider = (AuthorizationProvider) Class.forName(providerClassname)
.getDeclaredConstructor().newInstance();
provider.initialize(conf, pulsarResources);
+ this.resources = pulsarResources;
log.info("{} has been loaded.", providerClassname);
} else {
throw new PulsarServerException("No authorization providers are present.");
@@ -72,6 +76,23 @@ public AuthorizationService(ServiceConfiguration conf, PulsarResources pulsarRes
}
}
+ public CompletableFuture isSuperUser(AuthenticationParameters authParams) {
+ if (!isValidOriginalPrincipal(authParams)) {
+ return CompletableFuture.completedFuture(false);
+ }
+ if (isProxyRole(authParams.getClientRole())) {
+ CompletableFuture isRoleAuthorizedFuture = isSuperUser(authParams.getClientRole(),
+ authParams.getClientAuthenticationDataSource());
+ // The current paradigm is to pass the client auth data when we don't have access to the original auth data.
+ CompletableFuture isOriginalAuthorizedFuture = isSuperUser(authParams.getOriginalPrincipal(),
+ authParams.getClientAuthenticationDataSource());
+ return isRoleAuthorizedFuture.thenCombine(isOriginalAuthorizedFuture,
+ (isRoleAuthorized, isOriginalAuthorized) -> isRoleAuthorized && isOriginalAuthorized);
+ } else {
+ return isSuperUser(authParams.getClientRole(), authParams.getClientAuthenticationDataSource());
+ }
+ }
+
public CompletableFuture isSuperUser(String user, AuthenticationDataSource authenticationData) {
return provider.isSuperUser(user, authenticationData, conf);
}
@@ -279,17 +300,118 @@ public CompletableFuture canLookupAsync(TopicName topicName, String rol
public CompletableFuture allowFunctionOpsAsync(NamespaceName namespaceName, String role,
AuthenticationDataSource authenticationData) {
- return provider.allowFunctionOpsAsync(namespaceName, role, authenticationData);
+ return isSuperUserOrAdmin(namespaceName, role, authenticationData)
+ .thenCompose(isSuperUserOrAdmin -> isSuperUserOrAdmin
+ ? CompletableFuture.completedFuture(true)
+ : provider.allowFunctionOpsAsync(namespaceName, role, authenticationData)
+ );
+ }
+
+ public CompletableFuture allowFunctionOpsAsync(NamespaceName namespaceName,
+ AuthenticationParameters authParams) {
+ if (!isValidOriginalPrincipal(authParams)) {
+ return CompletableFuture.completedFuture(false);
+ }
+ if (isProxyRole(authParams.getClientRole())) {
+ CompletableFuture isRoleAuthorizedFuture = allowFunctionOpsAsync(namespaceName,
+ authParams.getClientRole(), authParams.getClientAuthenticationDataSource());
+ // The current paradigm is to pass the client auth data when we don't have access to the original auth data.
+ CompletableFuture isOriginalAuthorizedFuture = allowFunctionOpsAsync(
+ namespaceName, authParams.getOriginalPrincipal(), authParams.getClientAuthenticationDataSource());
+ return isRoleAuthorizedFuture.thenCombine(isOriginalAuthorizedFuture,
+ (isRoleAuthorized, isOriginalAuthorized) -> isRoleAuthorized && isOriginalAuthorized);
+ } else {
+ return allowFunctionOpsAsync(namespaceName, authParams.getClientRole(),
+ authParams.getClientAuthenticationDataSource());
+ }
}
public CompletableFuture allowSourceOpsAsync(NamespaceName namespaceName, String role,
AuthenticationDataSource authenticationData) {
- return provider.allowSourceOpsAsync(namespaceName, role, authenticationData);
+ return isSuperUserOrAdmin(namespaceName, role, authenticationData)
+ .thenCompose(isSuperUserOrAdmin -> isSuperUserOrAdmin
+ ? CompletableFuture.completedFuture(true)
+ : provider.allowSourceOpsAsync(namespaceName, role, authenticationData)
+ );
+ }
+
+ public CompletableFuture allowSourceOpsAsync(NamespaceName namespaceName,
+ AuthenticationParameters authParams) {
+ if (!isValidOriginalPrincipal(authParams)) {
+ return CompletableFuture.completedFuture(false);
+ }
+ if (isProxyRole(authParams.getClientRole())) {
+ CompletableFuture isRoleAuthorizedFuture = allowSourceOpsAsync(namespaceName,
+ authParams.getClientRole(), authParams.getClientAuthenticationDataSource());
+ // The current paradigm is to pass the client auth data when we don't have access to the original auth data.
+ CompletableFuture isOriginalAuthorizedFuture = allowSourceOpsAsync(
+ namespaceName, authParams.getOriginalPrincipal(), authParams.getClientAuthenticationDataSource());
+ return isRoleAuthorizedFuture.thenCombine(isOriginalAuthorizedFuture,
+ (isRoleAuthorized, isOriginalAuthorized) -> isRoleAuthorized && isOriginalAuthorized);
+ } else {
+ return allowSourceOpsAsync(namespaceName, authParams.getClientRole(),
+ authParams.getClientAuthenticationDataSource());
+ }
}
public CompletableFuture allowSinkOpsAsync(NamespaceName namespaceName, String role,
AuthenticationDataSource authenticationData) {
- return provider.allowSinkOpsAsync(namespaceName, role, authenticationData);
+ return isSuperUserOrAdmin(namespaceName, role, authenticationData)
+ .thenCompose(isSuperUserOrAdmin -> isSuperUserOrAdmin
+ ? CompletableFuture.completedFuture(true)
+ : provider.allowSinkOpsAsync(namespaceName, role, authenticationData)
+ );
+ }
+
+ public CompletableFuture allowSinkOpsAsync(NamespaceName namespaceName,
+ AuthenticationParameters authParams) {
+ if (!isValidOriginalPrincipal(authParams)) {
+ return CompletableFuture.completedFuture(false);
+ }
+ if (isProxyRole(authParams.getClientRole())) {
+ CompletableFuture isRoleAuthorizedFuture = allowSinkOpsAsync(namespaceName,
+ authParams.getClientRole(), authParams.getClientAuthenticationDataSource());
+ // The current paradigm is to pass the client auth data when we don't have access to the original auth data.
+ CompletableFuture isOriginalAuthorizedFuture = allowSinkOpsAsync(
+ namespaceName, authParams.getOriginalPrincipal(), authParams.getClientAuthenticationDataSource());
+ return isRoleAuthorizedFuture.thenCombine(isOriginalAuthorizedFuture,
+ (isRoleAuthorized, isOriginalAuthorized) -> isRoleAuthorized && isOriginalAuthorized);
+ } else {
+ return allowSinkOpsAsync(namespaceName, authParams.getClientRole(),
+ authParams.getClientAuthenticationDataSource());
+ }
+ }
+
+ /**
+ * Functions, sources, and sinks each have their own method in this class. This method first checks for
+ * tenant admin access, then for namespace level permission.
+ */
+ private CompletableFuture isSuperUserOrAdmin(NamespaceName namespaceName,
+ String role,
+ AuthenticationDataSource authenticationData) {
+ return isSuperUser(role, authenticationData)
+ .thenCompose(isSuperUserOrAdmin -> isSuperUserOrAdmin
+ ? CompletableFuture.completedFuture(true)
+ : isTenantAdmin(namespaceName.getTenant(), role, authenticationData));
+ }
+
+ private CompletableFuture isTenantAdmin(String tenant, String role,
+ AuthenticationDataSource authData) {
+ return resources.getTenantResources()
+ .getTenantAsync(tenant)
+ .thenCompose(op -> {
+ if (op.isPresent()) {
+ return isTenantAdmin(tenant, role, op.get(), authData);
+ } else {
+ return CompletableFuture.failedFuture(new RestException(Response.Status.NOT_FOUND,
+ "Tenant does not exist"));
+ }
+ });
+ }
+
+ private boolean isValidOriginalPrincipal(AuthenticationParameters authParams) {
+ return isValidOriginalPrincipal(authParams.getClientRole(),
+ authParams.getOriginalPrincipal(), authParams.getClientAuthenticationDataSource());
}
/**
diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/PulsarService.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/PulsarService.java
index 4af94c339c82f..b2eefe298b53c 100644
--- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/PulsarService.java
+++ b/pulsar-broker/src/main/java/org/apache/pulsar/broker/PulsarService.java
@@ -1860,6 +1860,7 @@ public static WorkerConfig initializeWorkerConfigFromBrokerConfig(ServiceConfigu
// inherit super users
workerConfig.setSuperUserRoles(brokerConfig.getSuperUserRoles());
+ workerConfig.setProxyRoles(brokerConfig.getProxyRoles());
workerConfig.setFunctionsWorkerEnablePackageManagement(brokerConfig.isFunctionsWorkerEnablePackageManagement());
// inherit the nar package locations
diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/BrokerStatsBase.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/BrokerStatsBase.java
index 670fa10b28b88..6d49dd81da13d 100644
--- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/BrokerStatsBase.java
+++ b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/BrokerStatsBase.java
@@ -159,6 +159,7 @@ public LoadManagerReport getLoadReport() throws Exception {
protected Map> internalBrokerResourceAvailability(NamespaceName namespace) {
try {
+ validateSuperUserAccess();
LoadManager lm = pulsar().getLoadManager().get();
if (lm instanceof SimpleLoadManagerImpl) {
return ((SimpleLoadManagerImpl) lm).getResourceAvailabilityFor(namespace).asMap();
diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/FunctionsBase.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/FunctionsBase.java
index bee81bf5dcdb6..4350316e2f011 100644
--- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/FunctionsBase.java
+++ b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/FunctionsBase.java
@@ -194,7 +194,7 @@ public void registerFunction(
)
final @FormDataParam("functionConfig") FunctionConfig functionConfig) {
functions().registerFunction(tenant, namespace, functionName, uploadedInputStream, fileDetail,
- functionPkgUrl, functionConfig, clientAppId(), clientAuthData());
+ functionPkgUrl, functionConfig, authParams());
}
@PUT
@@ -322,7 +322,7 @@ public void updateFunction(
final @FormDataParam("updateOptions") UpdateOptionsImpl updateOptions) throws IOException {
functions().updateFunction(tenant, namespace, functionName, uploadedInputStream, fileDetail,
- functionPkgUrl, functionConfig, clientAppId(), clientAuthData(), updateOptions);
+ functionPkgUrl, functionConfig, authParams(), updateOptions);
}
@@ -343,7 +343,7 @@ public void deregisterFunction(
final @PathParam("namespace") String namespace,
@ApiParam(value = "The name of a Pulsar Function")
final @PathParam("functionName") String functionName) {
- functions().deregisterFunction(tenant, namespace, functionName, clientAppId(), clientAuthData());
+ functions().deregisterFunction(tenant, namespace, functionName, authParams());
}
@GET
@@ -365,7 +365,7 @@ public FunctionConfig getFunctionInfo(
final @PathParam("namespace") String namespace,
@ApiParam(value = "The name of a Pulsar Function")
final @PathParam("functionName") String functionName) throws IOException {
- return functions().getFunctionInfo(tenant, namespace, functionName, clientAppId(), clientAuthData());
+ return functions().getFunctionInfo(tenant, namespace, functionName, authParams());
}
@GET
@@ -389,7 +389,7 @@ public FunctionStatus.FunctionInstanceStatus.FunctionInstanceStatusData getFunct
+ " the stats of all instances is returned") final @PathParam("instanceId")
String instanceId) throws IOException {
return functions().getFunctionInstanceStatus(tenant, namespace, functionName,
- instanceId, uri.getRequestUri(), clientAppId(), clientAuthData());
+ instanceId, uri.getRequestUri(), authParams());
}
@GET
@@ -413,7 +413,7 @@ public FunctionStatus getFunctionStatus(
@ApiParam(value = "The name of a Pulsar Function")
final @PathParam("functionName") String functionName) throws IOException {
return functions().getFunctionStatus(tenant, namespace, functionName, uri.getRequestUri(),
- clientAppId(), clientAuthData());
+ authParams());
}
@GET
@@ -437,7 +437,7 @@ public FunctionStatsImpl getFunctionStats(
@ApiParam(value = "The name of a Pulsar Function")
final @PathParam("functionName") String functionName) throws IOException {
return functions().getFunctionStats(tenant, namespace, functionName,
- uri.getRequestUri(), clientAppId(), clientAuthData());
+ uri.getRequestUri(), authParams());
}
@GET
@@ -461,7 +461,7 @@ public FunctionInstanceStatsDataImpl getFunctionInstanceStats(
+ " (if instance-id is not provided, the stats of all instances is returned") final @PathParam(
"instanceId") String instanceId) throws IOException {
return functions().getFunctionsInstanceStats(tenant, namespace, functionName, instanceId,
- uri.getRequestUri(), clientAppId(), clientAuthData());
+ uri.getRequestUri(), authParams());
}
@GET
@@ -480,7 +480,7 @@ public List listFunctions(
final @PathParam("tenant") String tenant,
@ApiParam(value = "The namespace of a Pulsar Function")
final @PathParam("namespace") String namespace) {
- return functions().listFunctions(tenant, namespace, clientAppId(), clientAuthData());
+ return functions().listFunctions(tenant, namespace, authParams());
}
@POST
@@ -509,7 +509,7 @@ public String triggerFunction(
+ " consumes from which you want to inject the data to") final @FormDataParam("topic")
String topic) {
return functions().triggerFunction(tenant, namespace, functionName, triggerValue,
- triggerStream, topic, clientAppId(), clientAuthData());
+ triggerStream, topic, authParams());
}
@GET
@@ -533,7 +533,7 @@ public FunctionState getFunctionState(
final @PathParam("functionName") String functionName,
@ApiParam(value = "The stats key")
final @PathParam("key") String key) {
- return functions().getFunctionState(tenant, namespace, functionName, key, clientAppId(), clientAuthData());
+ return functions().getFunctionState(tenant, namespace, functionName, key, authParams());
}
@POST
@@ -553,7 +553,7 @@ public void putFunctionState(final @PathParam("tenant") String tenant,
final @PathParam("functionName") String functionName,
final @PathParam("key") String key,
final @FormDataParam("state") FunctionState stateJson) {
- functions().putFunctionState(tenant, namespace, functionName, key, stateJson, clientAppId(), clientAuthData());
+ functions().putFunctionState(tenant, namespace, functionName, key, stateJson, authParams());
}
@POST
@@ -574,7 +574,7 @@ public void restartFunction(
"The instanceId of a Pulsar Function (if instance-id is not provided, all instances are restarted")
final @PathParam("instanceId") String instanceId) {
functions().restartFunctionInstance(tenant, namespace, functionName, instanceId,
- uri.getRequestUri(), clientAppId(), clientAuthData());
+ uri.getRequestUri(), authParams());
}
@POST
@@ -593,7 +593,7 @@ public void restartFunction(
final @PathParam("namespace") String namespace,
@ApiParam(value = "The name of a Pulsar Function")
final @PathParam("functionName") String functionName) {
- functions().restartFunctionInstances(tenant, namespace, functionName, clientAppId(), clientAuthData());
+ functions().restartFunctionInstances(tenant, namespace, functionName, authParams());
}
@POST
@@ -613,7 +613,7 @@ public void stopFunction(
"The instanceId of a Pulsar Function (if instance-id is not provided, all instances are stopped. ")
final @PathParam("instanceId") String instanceId) {
functions().stopFunctionInstance(tenant, namespace, functionName, instanceId,
- uri.getRequestUri(), clientAppId(), clientAuthData());
+ uri.getRequestUri(), authParams());
}
@POST
@@ -632,7 +632,7 @@ public void stopFunction(
final @PathParam("namespace") String namespace,
@ApiParam(value = "The name of a Pulsar Function")
final @PathParam("functionName") String functionName) {
- functions().stopFunctionInstances(tenant, namespace, functionName, clientAppId(), clientAuthData());
+ functions().stopFunctionInstances(tenant, namespace, functionName, authParams());
}
@POST
@@ -652,7 +652,7 @@ public void startFunction(
+ " (if instance-id is not provided, all instances sre started. ") final @PathParam("instanceId")
String instanceId) {
functions().startFunctionInstance(tenant, namespace, functionName, instanceId,
- uri.getRequestUri(), clientAppId(), clientAuthData());
+ uri.getRequestUri(), authParams());
}
@POST
@@ -671,7 +671,7 @@ public void startFunction(
final @PathParam("namespace") String namespace,
@ApiParam(value = "The name of a Pulsar Function")
final @PathParam("functionName") String functionName) {
- functions().startFunctionInstances(tenant, namespace, functionName, clientAppId(), clientAuthData());
+ functions().startFunctionInstances(tenant, namespace, functionName, authParams());
}
@POST
@@ -683,7 +683,7 @@ public void startFunction(
@Consumes(MediaType.MULTIPART_FORM_DATA)
public void uploadFunction(final @FormDataParam("data") InputStream uploadedInputStream,
final @FormDataParam("path") String path) {
- functions().uploadFunction(uploadedInputStream, path, clientAppId(), clientAuthData());
+ functions().uploadFunction(uploadedInputStream, path, authParams());
}
@GET
@@ -693,7 +693,7 @@ public void uploadFunction(final @FormDataParam("data") InputStream uploadedInpu
)
@Path("/download")
public StreamingOutput downloadFunction(final @QueryParam("path") String path) {
- return functions().downloadFunction(path, clientAppId(), clientAuthData());
+ return functions().downloadFunction(path, authParams());
}
@GET
@@ -712,8 +712,7 @@ public StreamingOutput downloadFunction(
@ApiParam(value = "Whether to download the transform-function")
final @QueryParam("transform-function") boolean transformFunction) {
- return functions()
- .downloadFunction(tenant, namespace, functionName, clientAppId(), clientAuthData(), transformFunction);
+ return functions().downloadFunction(tenant, namespace, functionName, authParams(), transformFunction);
}
@GET
@@ -746,7 +745,7 @@ public List getConnectorsList() throws IOException {
})
@Path("/builtins/reload")
public void reloadBuiltinFunctions() throws IOException {
- functions().reloadBuiltinFunctions(clientAppId(), clientAuthData());
+ functions().reloadBuiltinFunctions(authParams());
}
@GET
@@ -763,7 +762,7 @@ public void reloadBuiltinFunctions() throws IOException {
@Path("/builtins")
@Produces(MediaType.APPLICATION_JSON)
public List getBuiltinFunction() {
- return functions().getBuiltinFunctions(clientAppId(), clientAuthData());
+ return functions().getBuiltinFunctions(authParams());
}
@PUT
@@ -785,6 +784,6 @@ public void updateFunctionOnWorkerLeader(final @PathParam("tenant") String tenan
final @FormDataParam("delete") boolean delete) {
functions().updateFunctionOnWorkerLeader(tenant, namespace, functionName, uploadedInputStream,
- delete, uri.getRequestUri(), clientAppId(), clientAuthData());
+ delete, uri.getRequestUri(), authParams());
}
}
diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/SinksBase.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/SinksBase.java
index 7a3a554a3a00c..80ad72d6f9aa9 100644
--- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/SinksBase.java
+++ b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/SinksBase.java
@@ -168,7 +168,7 @@ public void registerSink(@ApiParam(value = "The tenant of a Pulsar Sink") final
)
final @FormDataParam("sinkConfig") SinkConfig sinkConfig) {
sinks().registerSink(tenant, namespace, sinkName, uploadedInputStream, fileDetail,
- sinkPkgUrl, sinkConfig, clientAppId(), clientAuthData());
+ sinkPkgUrl, sinkConfig, authParams());
}
@PUT
@@ -271,7 +271,7 @@ public void updateSink(@ApiParam(value = "The tenant of a Pulsar Sink") final @P
@ApiParam(value = "Update options for the Pulsar Sink")
final @FormDataParam("updateOptions") UpdateOptionsImpl updateOptions) {
sinks().updateSink(tenant, namespace, sinkName, uploadedInputStream, fileDetail,
- sinkPkgUrl, sinkConfig, clientAppId(), clientAuthData(), updateOptions);
+ sinkPkgUrl, sinkConfig, authParams(), updateOptions);
}
@@ -295,7 +295,7 @@ public void deregisterSink(@ApiParam(value = "The tenant of a Pulsar Sink")
final @PathParam("namespace") String namespace,
@ApiParam(value = "The name of a Pulsar Sink")
final @PathParam("sinkName") String sinkName) {
- sinks().deregisterFunction(tenant, namespace, sinkName, clientAppId(), clientAuthData());
+ sinks().deregisterFunction(tenant, namespace, sinkName, authParams());
}
@GET
@@ -315,7 +315,7 @@ public SinkConfig getSinkInfo(@ApiParam(value = "The tenant of a Pulsar Sink")
final @PathParam("namespace") String namespace,
@ApiParam(value = "The name of a Pulsar Sink")
final @PathParam("sinkName") String sinkName) throws IOException {
- return sinks().getSinkInfo(tenant, namespace, sinkName);
+ return sinks().getSinkInfo(tenant, namespace, sinkName, authParams());
}
@GET
@@ -342,7 +342,7 @@ public SinkStatus.SinkInstanceStatus.SinkInstanceStatusData getSinkInstanceStatu
@ApiParam(value = "The instanceId of a Pulsar Sink")
final @PathParam("instanceId") String instanceId) throws IOException {
return sinks().getSinkInstanceStatus(
- tenant, namespace, sinkName, instanceId, uri.getRequestUri(), clientAppId(), clientAuthData());
+ tenant, namespace, sinkName, instanceId, uri.getRequestUri(), authParams());
}
@GET
@@ -365,7 +365,7 @@ public SinkStatus getSinkStatus(@ApiParam(value = "The tenant of a Pulsar Sink")
final @PathParam("namespace") String namespace,
@ApiParam(value = "The name of a Pulsar Sink")
final @PathParam("sinkName") String sinkName) throws IOException {
- return sinks().getSinkStatus(tenant, namespace, sinkName, uri.getRequestUri(), clientAppId(), clientAuthData());
+ return sinks().getSinkStatus(tenant, namespace, sinkName, uri.getRequestUri(), authParams());
}
@GET
@@ -385,7 +385,7 @@ public List listSinks(@ApiParam(value = "The tenant of a Pulsar Sink")
final @PathParam("tenant") String tenant,
@ApiParam(value = "The namespace of a Pulsar Sink")
final @PathParam("namespace") String namespace) {
- return sinks().listFunctions(tenant, namespace, clientAppId(), clientAuthData());
+ return sinks().listFunctions(tenant, namespace, authParams());
}
@POST
@@ -411,7 +411,7 @@ public void restartSink(@ApiParam(value = "The tenant of a Pulsar Sink")
@ApiParam(value = "The instanceId of a Pulsar Sink")
final @PathParam("instanceId") String instanceId) {
sinks().restartFunctionInstance(tenant, namespace, sinkName, instanceId,
- uri.getRequestUri(), clientAppId(), clientAuthData());
+ uri.getRequestUri(), authParams());
}
@POST
@@ -432,7 +432,7 @@ public void restartSink(@ApiParam(value = "The tenant of a Pulsar Sink")
final @PathParam("namespace") String namespace,
@ApiParam(value = "The name of a Pulsar Sink")
final @PathParam("sinkName") String sinkName) {
- sinks().restartFunctionInstances(tenant, namespace, sinkName, clientAppId(), clientAuthData());
+ sinks().restartFunctionInstances(tenant, namespace, sinkName, authParams());
}
@POST
@@ -456,7 +456,7 @@ public void stopSink(@ApiParam(value = "The tenant of a Pulsar Sink")
@ApiParam(value = "The instanceId of a Pulsar Sink")
final @PathParam("instanceId") String instanceId) {
sinks().stopFunctionInstance(tenant, namespace,
- sinkName, instanceId, uri.getRequestUri(), clientAppId(), clientAuthData());
+ sinkName, instanceId, uri.getRequestUri(), authParams());
}
@POST
@@ -477,7 +477,7 @@ public void stopSink(@ApiParam(value = "The tenant of a Pulsar Sink")
final @PathParam("namespace") String namespace,
@ApiParam(value = "The name of a Pulsar Sink")
final @PathParam("sinkName") String sinkName) {
- sinks().stopFunctionInstances(tenant, namespace, sinkName, clientAppId(), clientAuthData());
+ sinks().stopFunctionInstances(tenant, namespace, sinkName, authParams());
}
@POST
@@ -501,7 +501,7 @@ public void startSink(@ApiParam(value = "The tenant of a Pulsar Sink")
@ApiParam(value = "The instanceId of a Pulsar Sink")
final @PathParam("instanceId") String instanceId) {
sinks().startFunctionInstance(tenant, namespace, sinkName, instanceId,
- uri.getRequestUri(), clientAppId(), clientAuthData());
+ uri.getRequestUri(), authParams());
}
@POST
@@ -522,7 +522,7 @@ public void startSink(@ApiParam(value = "The tenant of a Pulsar Sink")
final @PathParam("namespace") String namespace,
@ApiParam(value = "The name of a Pulsar Sink")
final @PathParam("sinkName") String sinkName) {
- sinks().startFunctionInstances(tenant, namespace, sinkName, clientAppId(), clientAuthData());
+ sinks().startFunctionInstances(tenant, namespace, sinkName, authParams());
}
@GET
@@ -571,6 +571,6 @@ public List getSinkConfigDefinition(
})
@Path("/reloadBuiltInSinks")
public void reloadSinks() {
- sinks().reloadConnectors(clientAppId(), clientAuthData());
+ sinks().reloadConnectors(authParams());
}
}
diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/SourcesBase.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/SourcesBase.java
index 1bf092784dd3a..4af0afc0d6ec5 100644
--- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/SourcesBase.java
+++ b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/SourcesBase.java
@@ -142,7 +142,7 @@ public void registerSource(
)
final @FormDataParam("sourceConfig") SourceConfig sourceConfig) {
sources().registerSource(tenant, namespace, sourceName, uploadedInputStream, fileDetail,
- sourcePkgUrl, sourceConfig, clientAppId(), clientAuthData());
+ sourcePkgUrl, sourceConfig, authParams());
}
@PUT
@@ -227,7 +227,7 @@ public void updateSource(
@ApiParam(value = "Update options for Pulsar Source")
final @FormDataParam("updateOptions") UpdateOptionsImpl updateOptions) {
sources().updateSource(tenant, namespace, sourceName, uploadedInputStream, fileDetail,
- sourcePkgUrl, sourceConfig, clientAppId(), clientAuthData(), updateOptions);
+ sourcePkgUrl, sourceConfig, authParams(), updateOptions);
}
@@ -250,7 +250,7 @@ public void deregisterSource(
final @PathParam("namespace") String namespace,
@ApiParam(value = "The name of a Pulsar Source")
final @PathParam("sourceName") String sourceName) {
- sources().deregisterFunction(tenant, namespace, sourceName, clientAppId(), clientAuthData());
+ sources().deregisterFunction(tenant, namespace, sourceName, authParams());
}
@GET
@@ -271,7 +271,7 @@ public SourceConfig getSourceInfo(
final @PathParam("namespace") String namespace,
@ApiParam(value = "The name of a Pulsar Source")
final @PathParam("sourceName") String sourceName) throws IOException {
- return sources().getSourceInfo(tenant, namespace, sourceName);
+ return sources().getSourceInfo(tenant, namespace, sourceName, authParams());
}
@GET
@@ -294,7 +294,7 @@ public SourceStatus.SourceInstanceStatus.SourceInstanceStatusData getSourceInsta
+ " (if instance-id is not provided, the stats of all instances is returned).") final @PathParam(
"instanceId") String instanceId) throws IOException {
return sources().getSourceInstanceStatus(
- tenant, namespace, sourceName, instanceId, uri.getRequestUri(), clientAppId(), clientAuthData());
+ tenant, namespace, sourceName, instanceId, uri.getRequestUri(), authParams());
}
@GET
@@ -316,8 +316,7 @@ public SourceStatus getSourceStatus(
final @PathParam("namespace") String namespace,
@ApiParam(value = "The name of a Pulsar Source")
final @PathParam("sourceName") String sourceName) throws IOException {
- return sources().getSourceStatus(tenant, namespace, sourceName, uri.getRequestUri(), clientAppId(),
- clientAuthData());
+ return sources().getSourceStatus(tenant, namespace, sourceName, uri.getRequestUri(), authParams());
}
@GET
@@ -339,7 +338,7 @@ public List listSources(
final @PathParam("tenant") String tenant,
@ApiParam(value = "The namespace of a Pulsar Source")
final @PathParam("namespace") String namespace) {
- return sources().listFunctions(tenant, namespace, clientAppId(), clientAuthData());
+ return sources().listFunctions(tenant, namespace, authParams());
}
@POST
@@ -362,7 +361,7 @@ public void restartSource(
+ " (if instance-id is not provided, the stats of all instances is returned).") final @PathParam(
"instanceId") String instanceId) {
sources().restartFunctionInstance(tenant, namespace, sourceName, instanceId,
- uri.getRequestUri(), clientAppId(), clientAuthData());
+ uri.getRequestUri(), authParams());
}
@POST
@@ -383,7 +382,7 @@ public void restartSource(
final @PathParam("namespace") String namespace,
@ApiParam(value = "The name of a Pulsar Source")
final @PathParam("sourceName") String sourceName) {
- sources().restartFunctionInstances(tenant, namespace, sourceName, clientAppId(), clientAuthData());
+ sources().restartFunctionInstances(tenant, namespace, sourceName, authParams());
}
@POST
@@ -404,7 +403,7 @@ public void stopSource(
@ApiParam(value = "The instanceId of a Pulsar Source (if instance-id is not provided,"
+ " the stats of all instances is returned).") final @PathParam("instanceId") String instanceId) {
sources().stopFunctionInstance(tenant, namespace, sourceName, instanceId,
- uri.getRequestUri(), clientAppId(), clientAuthData());
+ uri.getRequestUri(), authParams());
}
@POST
@@ -425,7 +424,7 @@ public void stopSource(
final @PathParam("namespace") String namespace,
@ApiParam(value = "The name of a Pulsar Source")
final @PathParam("sourceName") String sourceName) {
- sources().stopFunctionInstances(tenant, namespace, sourceName, clientAppId(), clientAuthData());
+ sources().stopFunctionInstances(tenant, namespace, sourceName, authParams());
}
@POST
@@ -446,7 +445,7 @@ public void startSource(
@ApiParam(value = "The instanceId of a Pulsar Source (if instance-id is not provided,"
+ " the stats of all instances is returned).") final @PathParam("instanceId") String instanceId) {
sources().startFunctionInstance(tenant, namespace, sourceName, instanceId,
- uri.getRequestUri(), clientAppId(), clientAuthData());
+ uri.getRequestUri(), authParams());
}
@POST
@@ -467,7 +466,7 @@ public void startSource(
final @PathParam("namespace") String namespace,
@ApiParam(value = "The name of a Pulsar Source")
final @PathParam("sourceName") String sourceName) {
- sources().startFunctionInstances(tenant, namespace, sourceName, clientAppId(), clientAuthData());
+ sources().startFunctionInstances(tenant, namespace, sourceName, authParams());
}
@GET
@@ -520,6 +519,6 @@ public List getSourceConfigDefinition(
})
@Path("/reloadBuiltInSources")
public void reloadSources() {
- sources().reloadConnectors(clientAppId(), clientAuthData());
+ sources().reloadConnectors(authParams());
}
}
diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v2/Functions.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v2/Functions.java
index 0d302bec065bc..69f99a42d0685 100644
--- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v2/Functions.java
+++ b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v2/Functions.java
@@ -75,7 +75,7 @@ public Response registerFunction(final @PathParam("tenant") String tenant,
final @FormDataParam("functionDetails") String functionDetailsJson) {
return functions().registerFunction(tenant, namespace, functionName, uploadedInputStream, fileDetail,
- functionPkgUrl, functionDetailsJson, clientAppId());
+ functionPkgUrl, functionDetailsJson, authParams());
}
@PUT
@@ -96,7 +96,7 @@ public Response updateFunction(final @PathParam("tenant") String tenant,
final @FormDataParam("functionDetails") String functionDetailsJson) {
return functions().updateFunction(tenant, namespace, functionName, uploadedInputStream, fileDetail,
- functionPkgUrl, functionDetailsJson, clientAppId());
+ functionPkgUrl, functionDetailsJson, authParams());
}
@@ -113,7 +113,7 @@ public Response updateFunction(final @PathParam("tenant") String tenant,
public Response deregisterFunction(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace,
final @PathParam("functionName") String functionName) {
- return functions().deregisterFunction(tenant, namespace, functionName, clientAppId());
+ return functions().deregisterFunction(tenant, namespace, functionName, authParams());
}
@GET
@@ -132,8 +132,7 @@ public Response getFunctionInfo(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace,
final @PathParam("functionName") String functionName) throws IOException {
- return functions().getFunctionInfo(
- tenant, namespace, functionName, clientAppId());
+ return functions().getFunctionInfo(tenant, namespace, functionName, authParams());
}
@GET
@@ -154,7 +153,7 @@ public Response getFunctionInstanceStatus(final @PathParam("tenant") String tena
final @PathParam("instanceId") String instanceId) throws IOException {
return functions().getFunctionInstanceStatus(tenant, namespace, functionName, instanceId, uri.getRequestUri(),
- clientAppId());
+ authParams());
}
@GET
@@ -172,7 +171,7 @@ public Response getFunctionStatus(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace,
final @PathParam("functionName") String functionName) throws IOException {
return functions().getFunctionStatusV2(
- tenant, namespace, functionName, uri.getRequestUri(), clientAppId());
+ tenant, namespace, functionName, uri.getRequestUri(), authParams());
}
@GET
@@ -188,7 +187,7 @@ public Response getFunctionStatus(final @PathParam("tenant") String tenant,
@Path("/{tenant}/{namespace}")
public Response listFunctions(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace) {
- return functions().listFunctions(tenant, namespace, clientAppId());
+ return functions().listFunctions(tenant, namespace, authParams());
}
@POST
@@ -211,7 +210,7 @@ public Response triggerFunction(final @PathParam("tenant") String tenant,
final @FormDataParam("dataStream") InputStream triggerStream,
final @FormDataParam("topic") String topic) {
return functions().triggerFunction(tenant, namespace, functionName,
- triggerValue, triggerStream, topic, clientAppId());
+ triggerValue, triggerStream, topic, authParams());
}
@GET
@@ -230,7 +229,7 @@ public Response getFunctionState(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace,
final @PathParam("functionName") String functionName,
final @PathParam("key") String key) {
- return functions().getFunctionState(tenant, namespace, functionName, key, clientAppId());
+ return functions().getFunctionState(tenant, namespace, functionName, key, authParams());
}
@POST
@@ -247,7 +246,7 @@ public Response restartFunction(final @PathParam("tenant") String tenant,
final @PathParam("functionName") String functionName,
final @PathParam("instanceId") String instanceId) {
return functions().restartFunctionInstance(tenant, namespace, functionName,
- instanceId, uri.getRequestUri(), clientAppId());
+ instanceId, uri.getRequestUri(), authParams());
}
@POST
@@ -260,7 +259,7 @@ public Response restartFunction(final @PathParam("tenant") String tenant,
public Response restartFunction(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace,
final @PathParam("functionName") String functionName) {
- return functions().restartFunctionInstances(tenant, namespace, functionName, clientAppId());
+ return functions().restartFunctionInstances(tenant, namespace, functionName, authParams());
}
@POST
@@ -275,7 +274,7 @@ public Response stopFunction(final @PathParam("tenant") String tenant,
final @PathParam("functionName") String functionName,
final @PathParam("instanceId") String instanceId) {
return functions().stopFunctionInstance(tenant, namespace, functionName,
- instanceId, uri.getRequestUri(), clientAppId());
+ instanceId, uri.getRequestUri(), authParams());
}
@POST
@@ -288,7 +287,7 @@ public Response stopFunction(final @PathParam("tenant") String tenant,
public Response stopFunction(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace,
final @PathParam("functionName") String functionName) {
- return functions().stopFunctionInstances(tenant, namespace, functionName, clientAppId());
+ return functions().stopFunctionInstances(tenant, namespace, functionName, authParams());
}
@POST
@@ -300,7 +299,7 @@ public Response stopFunction(final @PathParam("tenant") String tenant,
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFunction(final @FormDataParam("data") InputStream uploadedInputStream,
final @FormDataParam("path") String path) {
- return functions().uploadFunction(uploadedInputStream, path, clientAppId());
+ return functions().uploadFunction(uploadedInputStream, path, authParams());
}
@GET
@@ -310,7 +309,7 @@ public Response uploadFunction(final @FormDataParam("data") InputStream uploaded
)
@Path("/download")
public Response downloadFunction(final @QueryParam("path") String path) {
- return functions().downloadFunction(path, clientAppId());
+ return functions().downloadFunction(path, authParams());
}
@GET
diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v2/Worker.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v2/Worker.java
index 80c75b04917ce..3813790e4f428 100644
--- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v2/Worker.java
+++ b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v2/Worker.java
@@ -66,7 +66,7 @@ public WorkerService get() {
@Path("/cluster")
@Produces(MediaType.APPLICATION_JSON)
public List getCluster() {
- return workers().getCluster(clientAppId());
+ return workers().getCluster(authParams());
}
@GET
@@ -81,7 +81,7 @@ public List getCluster() {
@Path("/cluster/leader")
@Produces(MediaType.APPLICATION_JSON)
public WorkerInfo getClusterLeader() {
- return workers().getClusterLeader(clientAppId());
+ return workers().getClusterLeader(authParams());
}
@GET
@@ -96,7 +96,7 @@ public WorkerInfo getClusterLeader() {
@Path("/assignments")
@Produces(MediaType.APPLICATION_JSON)
public Map> getAssignments() {
- return workers().getAssignments(clientAppId());
+ return workers().getAssignments(authParams());
}
@GET
@@ -112,7 +112,7 @@ public Map> getAssignments() {
@Path("/connectors")
@Produces(MediaType.APPLICATION_JSON)
public List getConnectorsList() throws IOException {
- return workers().getListOfConnectors(clientAppId());
+ return workers().getListOfConnectors(authParams());
}
@PUT
@@ -126,7 +126,7 @@ public List getConnectorsList() throws IOException {
})
@Path("/rebalance")
public void rebalance() {
- workers().rebalance(uri.getRequestUri(), clientAppId());
+ workers().rebalance(uri.getRequestUri(), authParams());
}
@PUT
@@ -142,7 +142,7 @@ public void rebalance() {
})
@Path("/leader/drain")
public void drainAtLeader(@QueryParam("workerId") String workerId) {
- workers().drain(uri.getRequestUri(), workerId, clientAppId(), true);
+ workers().drain(uri.getRequestUri(), workerId, authParams(), true);
}
@PUT
@@ -158,7 +158,7 @@ public void drainAtLeader(@QueryParam("workerId") String workerId) {
})
@Path("/drain")
public void drain() {
- workers().drain(uri.getRequestUri(), null, clientAppId(), false);
+ workers().drain(uri.getRequestUri(), null, authParams(), false);
}
@GET
@@ -172,7 +172,7 @@ public void drain() {
})
@Path("/leader/drain")
public LongRunningProcessStatus getDrainStatusFromLeader(@QueryParam("workerId") String workerId) {
- return workers().getDrainStatus(uri.getRequestUri(), workerId, clientAppId(), true);
+ return workers().getDrainStatus(uri.getRequestUri(), workerId, authParams(), true);
}
@GET
@@ -186,7 +186,7 @@ public LongRunningProcessStatus getDrainStatusFromLeader(@QueryParam("workerId")
})
@Path("/drain")
public LongRunningProcessStatus getDrainStatus() {
- return workers().getDrainStatus(uri.getRequestUri(), null, clientAppId(), false);
+ return workers().getDrainStatus(uri.getRequestUri(), null, authParams(), false);
}
@GET
@@ -199,6 +199,6 @@ public LongRunningProcessStatus getDrainStatus() {
})
@Path("/cluster/leader/ready")
public Boolean isLeaderReady() {
- return workers().isLeaderReady(clientAppId());
+ return workers().isLeaderReady(authParams());
}
}
diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v2/WorkerStats.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v2/WorkerStats.java
index 5a77d81b6f1e3..1716b5e588c77 100644
--- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v2/WorkerStats.java
+++ b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v2/WorkerStats.java
@@ -56,7 +56,7 @@ public Workers extends WorkerService> workers() {
})
@Produces(MediaType.APPLICATION_JSON)
public Collection getMetrics() throws Exception {
- return workers().getWorkerMetrics(clientAppId());
+ return workers().getWorkerMetrics(authParams());
}
@GET
@@ -72,6 +72,6 @@ public Collection getMetrics() throws Exception {
})
@Produces(MediaType.APPLICATION_JSON)
public List getStats() throws IOException {
- return workers().getFunctionsMetrics(clientAppId());
+ return workers().getFunctionsMetrics(authParams());
}
}
diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/web/PulsarWebResource.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/web/PulsarWebResource.java
index a182e4733fdfe..3d23d7812543a 100644
--- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/web/PulsarWebResource.java
+++ b/pulsar-broker/src/main/java/org/apache/pulsar/broker/web/PulsarWebResource.java
@@ -54,6 +54,7 @@
import org.apache.pulsar.broker.PulsarService;
import org.apache.pulsar.broker.ServiceConfiguration;
import org.apache.pulsar.broker.authentication.AuthenticationDataSource;
+import org.apache.pulsar.broker.authentication.AuthenticationParameters;
import org.apache.pulsar.broker.authorization.AuthorizationService;
import org.apache.pulsar.broker.loadbalance.extensions.ExtensibleLoadManagerImpl;
import org.apache.pulsar.broker.namespace.LookupOptions;
@@ -143,6 +144,14 @@ public static String splitPath(String source, int slice) {
return PolicyPath.splitPath(source, slice);
}
+ public AuthenticationParameters authParams() {
+ return AuthenticationParameters.builder()
+ .originalPrincipal(originalPrincipal())
+ .clientRole(clientAppId())
+ .clientAuthenticationDataSource(clientAuthData())
+ .build();
+ }
+
/**
* Gets a caller id (IP + role).
*
diff --git a/pulsar-functions/runtime/src/main/java/org/apache/pulsar/functions/worker/WorkerConfig.java b/pulsar-functions/runtime/src/main/java/org/apache/pulsar/functions/worker/WorkerConfig.java
index b87477f78c641..3b8ddf774d162 100644
--- a/pulsar-functions/runtime/src/main/java/org/apache/pulsar/functions/worker/WorkerConfig.java
+++ b/pulsar-functions/runtime/src/main/java/org/apache/pulsar/functions/worker/WorkerConfig.java
@@ -563,6 +563,12 @@ public boolean isBrokerClientAuthenticationEnabled() {
)
private Set superUserRoles = new TreeSet<>();
+ @FieldContext(
+ category = CATEGORY_WORKER_SECURITY,
+ doc = "Role names that are treated as `proxy roles`. These are the only roles that can supply the "
+ + "originalPrincipal.")
+ private Set proxyRoles = new TreeSet<>();
+
@FieldContext(
category = CATEGORY_WORKER_SECURITY,
doc = "This is a regexp, which limits the range of possible ids which can connect to the Broker using SASL."
diff --git a/pulsar-functions/src/test/resources/test_worker_config.yml b/pulsar-functions/src/test/resources/test_worker_config.yml
index f0ecf2bd71bc6..a297788037035 100644
--- a/pulsar-functions/src/test/resources/test_worker_config.yml
+++ b/pulsar-functions/src/test/resources/test_worker_config.yml
@@ -23,6 +23,9 @@ pulsarServiceUrl: pulsar://localhost:6650
functionMetadataTopicName: test-function-metadata-topic
numFunctionPackageReplicas: 3
maxPendingAsyncRequests: 200
+proxyRoles:
+ - "proxyA"
+ - "proxyB"
properties:
# Fake Bookkeeper Client config to be applied to the DLog Bookkeeper Client
bookkeeper_testKey: "fakeValue"
diff --git a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/FunctionApiResource.java b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/FunctionApiResource.java
index d37f7f15c606e..cfce3d3e68912 100644
--- a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/FunctionApiResource.java
+++ b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/FunctionApiResource.java
@@ -24,12 +24,14 @@
import javax.ws.rs.core.Context;
import javax.ws.rs.core.UriInfo;
import org.apache.pulsar.broker.authentication.AuthenticationDataSource;
+import org.apache.pulsar.broker.authentication.AuthenticationParameters;
import org.apache.pulsar.broker.web.AuthenticationFilter;
import org.apache.pulsar.functions.worker.WorkerService;
public class FunctionApiResource implements Supplier {
public static final String ATTRIBUTE_FUNCTION_WORKER = "function-worker";
+ public static final String ORIGINAL_PRINCIPAL_HEADER = "X-Original-Principal";
private WorkerService workerService;
@Context
@@ -47,12 +49,28 @@ public synchronized WorkerService get() {
return this.workerService;
}
+ public AuthenticationParameters authParams() {
+ return AuthenticationParameters.builder()
+ .originalPrincipal(httpRequest.getHeader(ORIGINAL_PRINCIPAL_HEADER))
+ .clientRole(clientAppId())
+ .clientAuthenticationDataSource(clientAuthData())
+ .build();
+ }
+
+ /**
+ * @deprecated use {@link #authParams()} instead.
+ */
+ @Deprecated
public String clientAppId() {
return httpRequest != null
? (String) httpRequest.getAttribute(AuthenticationFilter.AuthenticatedRoleAttributeName)
: null;
}
+ /**
+ * @deprecated use {@link #authParams()} instead.
+ */
+ @Deprecated
public AuthenticationDataSource clientAuthData() {
return (AuthenticationDataSource) httpRequest.getAttribute(AuthenticationFilter.AuthenticatedDataAttributeName);
}
diff --git a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/ComponentImpl.java b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/ComponentImpl.java
index 0b6c2bbd61f55..7daa9c9aee8ed 100644
--- a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/ComponentImpl.java
+++ b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/ComponentImpl.java
@@ -67,6 +67,7 @@
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.pulsar.broker.authentication.AuthenticationDataSource;
+import org.apache.pulsar.broker.authentication.AuthenticationParameters;
import org.apache.pulsar.client.admin.PulsarAdminException;
import org.apache.pulsar.client.admin.internal.FunctionsImpl;
import org.apache.pulsar.client.api.Message;
@@ -84,7 +85,6 @@
import org.apache.pulsar.common.naming.TopicName;
import org.apache.pulsar.common.policies.data.FunctionInstanceStatsDataImpl;
import org.apache.pulsar.common.policies.data.FunctionStatsImpl;
-import org.apache.pulsar.common.policies.data.TenantInfoImpl;
import org.apache.pulsar.common.util.Codec;
import org.apache.pulsar.common.util.RestException;
import org.apache.pulsar.functions.instance.InstanceUtils;
@@ -456,23 +456,14 @@ private void deleteStatestoreTableAsync(String namespace, String table) {
public void deregisterFunction(final String tenant,
final String namespace,
final String componentName,
- final String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps) {
+ final AuthenticationParameters authParams) {
if (!isWorkerServiceAvailable()) {
throwUnavailableException();
}
- try {
- if (!isAuthorizedRole(tenant, namespace, clientRole, clientAuthenticationDataHttps)) {
- log.warn("{}/{}/{} Client [{}] is not authorized to deregister {}", tenant, namespace,
- componentName, clientRole, ComponentTypeUtils.toString(componentType));
- throw new RestException(Status.UNAUTHORIZED, "Client is not authorized to perform operation");
- }
- } catch (PulsarAdminException e) {
- log.error("{}/{}/{} Failed to authorize [{}]", tenant, namespace, componentName, e);
- throw new RestException(Status.INTERNAL_SERVER_ERROR, e.getMessage());
- }
+ throwRestExceptionIfUnauthorizedForNamespace(tenant, namespace, componentName, "deregister",
+ authParams);
// validate parameters
try {
@@ -540,23 +531,14 @@ private void deleteComponentFromStorage(String tenant, String namespace, String
public FunctionConfig getFunctionInfo(final String tenant,
final String namespace,
final String componentName,
- final String clientRole,
- final AuthenticationDataSource clientAuthenticationDataHttps) {
+ final AuthenticationParameters authParams) {
if (!isWorkerServiceAvailable()) {
throwUnavailableException();
}
- try {
- if (!isAuthorizedRole(tenant, namespace, clientRole, clientAuthenticationDataHttps)) {
- log.warn("{}/{}/{} Client [{}] is not authorized to get {}", tenant, namespace,
- componentName, clientRole, ComponentTypeUtils.toString(componentType));
- throw new RestException(Status.UNAUTHORIZED, "Client is not authorized to perform operation");
- }
- } catch (PulsarAdminException e) {
- log.error("{}/{}/{} Failed to authorize [{}]", tenant, namespace, componentName, e);
- throw new RestException(Status.INTERNAL_SERVER_ERROR, e.getMessage());
- }
+ throwRestExceptionIfUnauthorizedForNamespace(tenant, namespace, componentName, "get",
+ authParams);
// validate parameters
try {
@@ -591,10 +573,8 @@ public void stopFunctionInstance(final String tenant,
final String componentName,
final String instanceId,
final URI uri,
- final String clientRole,
- final AuthenticationDataSource clientAuthenticationDataHttps) {
- changeFunctionInstanceStatus(tenant, namespace, componentName, instanceId, false, uri, clientRole,
- clientAuthenticationDataHttps);
+ final AuthenticationParameters authParams) {
+ changeFunctionInstanceStatus(tenant, namespace, componentName, instanceId, false, uri, authParams);
}
@Override
@@ -603,12 +583,11 @@ public void startFunctionInstance(final String tenant,
final String componentName,
final String instanceId,
final URI uri,
- final String clientRole,
- final AuthenticationDataSource clientAuthenticationDataHttps) {
- changeFunctionInstanceStatus(tenant, namespace, componentName, instanceId, true, uri, clientRole,
- clientAuthenticationDataHttps);
+ final AuthenticationParameters authParams) {
+ changeFunctionInstanceStatus(tenant, namespace, componentName, instanceId, true, uri, authParams);
}
+ @Deprecated
public void changeFunctionInstanceStatus(final String tenant,
final String namespace,
final String componentName,
@@ -617,21 +596,27 @@ public void changeFunctionInstanceStatus(final String tenant,
final URI uri,
final String clientRole,
final AuthenticationDataSource clientAuthenticationDataHttps) {
+ AuthenticationParameters authParams = AuthenticationParameters.builder()
+ .clientRole(clientRole)
+ .clientAuthenticationDataSource(clientAuthenticationDataHttps)
+ .build();
+ changeFunctionInstanceStatus(tenant, namespace, componentName, instanceId, start, uri, authParams);
+ }
+
+ public void changeFunctionInstanceStatus(final String tenant,
+ final String namespace,
+ final String componentName,
+ final String instanceId,
+ final boolean start,
+ final URI uri,
+ final AuthenticationParameters authParams) {
if (!isWorkerServiceAvailable()) {
throwUnavailableException();
}
- try {
- if (!isAuthorizedRole(tenant, namespace, clientRole, clientAuthenticationDataHttps)) {
- log.warn("{}/{}/{} Client [{}] is not authorized to start/stop {}", tenant, namespace,
- componentName, clientRole, ComponentTypeUtils.toString(componentType));
- throw new RestException(Status.UNAUTHORIZED, "Client is not authorized to perform operation");
- }
- } catch (PulsarAdminException e) {
- log.error("{}/{}/{} Failed to authorize [{}]", tenant, namespace, componentName, e);
- throw new RestException(Status.INTERNAL_SERVER_ERROR, e.getMessage());
- }
+ throwRestExceptionIfUnauthorizedForNamespace(tenant, namespace, componentName, "start/stop",
+ authParams);
// validate parameters
try {
@@ -678,22 +663,13 @@ public void restartFunctionInstance(final String tenant,
final String componentName,
final String instanceId,
final URI uri,
- final String clientRole,
- final AuthenticationDataSource clientAuthenticationDataHttps) {
+ final AuthenticationParameters authParams) {
if (!isWorkerServiceAvailable()) {
throwUnavailableException();
}
- try {
- if (!isAuthorizedRole(tenant, namespace, clientRole, clientAuthenticationDataHttps)) {
- log.warn("{}/{}/{} Client [{}] is not authorized to restart {}", tenant, namespace,
- componentName, clientRole, ComponentTypeUtils.toString(componentType));
- throw new RestException(Status.UNAUTHORIZED, "Client is not authorized to perform operation");
- }
- } catch (PulsarAdminException e) {
- log.error("{}/{}/{} Failed to authorize [{}]", tenant, namespace, componentName, e);
- throw new RestException(Status.INTERNAL_SERVER_ERROR, e.getMessage());
- }
+ throwRestExceptionIfUnauthorizedForNamespace(tenant, namespace, componentName, "restart",
+ authParams);
// validate parameters
try {
@@ -738,43 +714,41 @@ public void restartFunctionInstance(final String tenant,
public void stopFunctionInstances(final String tenant,
final String namespace,
final String componentName,
- final String clientRole,
- final AuthenticationDataSource clientAuthenticationDataHttps) {
- changeFunctionStatusAllInstances(tenant, namespace, componentName, false, clientRole,
- clientAuthenticationDataHttps);
+ final AuthenticationParameters authParams) {
+ changeFunctionStatusAllInstances(tenant, namespace, componentName, false, authParams);
}
@Override
public void startFunctionInstances(final String tenant,
final String namespace,
final String componentName,
- final String clientRole,
- final AuthenticationDataSource clientAuthenticationDataHttps) {
- changeFunctionStatusAllInstances(tenant, namespace, componentName, true, clientRole,
- clientAuthenticationDataHttps);
+ final AuthenticationParameters authParams) {
+ changeFunctionStatusAllInstances(tenant, namespace, componentName, true, authParams);
}
+ @Deprecated
public void changeFunctionStatusAllInstances(final String tenant,
final String namespace,
final String componentName,
final boolean start,
final String clientRole,
final AuthenticationDataSource clientAuthenticationDataHttps) {
+ AuthenticationParameters authParams = AuthenticationParameters.builder().clientRole(clientRole)
+ .clientAuthenticationDataSource(clientAuthenticationDataHttps).build();
+ changeFunctionStatusAllInstances(tenant, namespace, componentName, start, authParams);
+ }
+ public void changeFunctionStatusAllInstances(final String tenant,
+ final String namespace,
+ final String componentName,
+ final boolean start,
+ final AuthenticationParameters authParams) {
if (!isWorkerServiceAvailable()) {
throwUnavailableException();
}
- try {
- if (!isAuthorizedRole(tenant, namespace, clientRole, clientAuthenticationDataHttps)) {
- log.warn("{}/{}/{} Client [{}] is not authorized to start/stop {}", tenant, namespace,
- componentName, clientRole, ComponentTypeUtils.toString(componentType));
- throw new RestException(Status.UNAUTHORIZED, "Client is not authorized to perform operation");
- }
- } catch (PulsarAdminException e) {
- log.error("{}/{}/{} Failed to authorize [{}]", tenant, namespace, componentName, e);
- throw new RestException(Status.INTERNAL_SERVER_ERROR, e.getMessage());
- }
+ throwRestExceptionIfUnauthorizedForNamespace(tenant, namespace, componentName, "start/stop",
+ authParams);
// validate parameters
try {
@@ -815,25 +789,17 @@ public void changeFunctionStatusAllInstances(final String tenant,
namespace, componentName));
}
+ @Override
public void restartFunctionInstances(final String tenant,
final String namespace,
final String componentName,
- final String clientRole,
- final AuthenticationDataSource clientAuthenticationDataHttps) {
+ final AuthenticationParameters authParams) {
if (!isWorkerServiceAvailable()) {
throwUnavailableException();
}
- try {
- if (!isAuthorizedRole(tenant, namespace, clientRole, clientAuthenticationDataHttps)) {
- log.warn("{}/{}/{} Client [{}] is not authorized to restart {}", tenant, namespace,
- componentName, clientRole, ComponentTypeUtils.toString(componentType));
- throw new RestException(Status.UNAUTHORIZED, "Client is not authorized to perform operation");
- }
- } catch (PulsarAdminException e) {
- log.error("{}/{}/{} Failed to authorize [{}]", tenant, namespace, componentName, e);
- throw new RestException(Status.INTERNAL_SERVER_ERROR, e.getMessage());
- }
+ throwRestExceptionIfUnauthorizedForNamespace(tenant, namespace, componentName, "restart",
+ authParams);
// validate parameters
try {
@@ -873,26 +839,18 @@ public void restartFunctionInstances(final String tenant,
}
}
+ @Override
public FunctionStatsImpl getFunctionStats(final String tenant,
final String namespace,
final String componentName,
final URI uri,
- final String clientRole,
- final AuthenticationDataSource clientAuthenticationDataHttps) {
+ final AuthenticationParameters authParams) {
if (!isWorkerServiceAvailable()) {
throwUnavailableException();
}
- try {
- if (!isAuthorizedRole(tenant, namespace, clientRole, clientAuthenticationDataHttps)) {
- log.warn("{}/{}/{} Client [{}] is not authorized to get stats for {}", tenant, namespace,
- componentName, clientRole, ComponentTypeUtils.toString(componentType));
- throw new RestException(Status.UNAUTHORIZED, "Client is not authorized to perform operation");
- }
- } catch (PulsarAdminException e) {
- log.error("{}/{}/{} Failed to authorize [{}]", tenant, namespace, componentName, e);
- throw new RestException(Status.INTERNAL_SERVER_ERROR, e.getMessage());
- }
+ throwRestExceptionIfUnauthorizedForNamespace(tenant, namespace, componentName, "get stats for",
+ authParams);
// validate parameters
try {
@@ -941,22 +899,13 @@ public FunctionStatsImpl getFunctionStats(final String tenant,
final String componentName,
final String instanceId,
final URI uri,
- final String clientRole,
- final AuthenticationDataSource clientAuthenticationDataHttps) {
+ final AuthenticationParameters authParams) {
if (!isWorkerServiceAvailable()) {
throwUnavailableException();
}
- try {
- if (!isAuthorizedRole(tenant, namespace, clientRole, clientAuthenticationDataHttps)) {
- log.warn("{}/{}/{} Client [{}] is not authorized to get stats for {}", tenant, namespace,
- componentName, clientRole, ComponentTypeUtils.toString(componentType));
- throw new RestException(Status.UNAUTHORIZED, "Client is not authorized to perform operation");
- }
- } catch (PulsarAdminException e) {
- log.error("{}/{}/{} Failed to authorize [{}]", tenant, namespace, componentName, e);
- throw new RestException(Status.INTERNAL_SERVER_ERROR, e.getMessage());
- }
+ throwRestExceptionIfUnauthorizedForNamespace(tenant, namespace, componentName, "get stats for",
+ authParams);
// validate parameters
try {
@@ -1012,23 +961,13 @@ public FunctionStatsImpl getFunctionStats(final String tenant,
@Override
public List listFunctions(final String tenant,
final String namespace,
- final String clientRole,
- final AuthenticationDataSource clientAuthenticationDataHttps) {
+ final AuthenticationParameters authParams) {
if (!isWorkerServiceAvailable()) {
throwUnavailableException();
}
- try {
- if (!isAuthorizedRole(tenant, namespace, clientRole, clientAuthenticationDataHttps)) {
- log.warn("{}/{} Client [{}] is not authorized to list {}", tenant, namespace, clientRole,
- ComponentTypeUtils.toString(componentType));
- throw new RestException(Status.UNAUTHORIZED, "Client is not authorized to perform operation");
- }
- } catch (PulsarAdminException e) {
- log.error("{}/{} Failed to authorize [{}]", tenant, namespace, e);
- throw new RestException(Status.INTERNAL_SERVER_ERROR, e.getMessage());
- }
+ throwRestExceptionIfUnauthorizedForNamespace(tenant, namespace, null, "list", authParams);
// validate parameters
try {
@@ -1070,13 +1009,13 @@ public List getListOfConnectors() {
}
@Override
- public void reloadConnectors(String clientRole, AuthenticationDataSource authenticationData) {
+ public void reloadConnectors(AuthenticationParameters authParams) {
if (!isWorkerServiceAvailable()) {
throwUnavailableException();
}
if (worker().getWorkerConfig().isAuthorizationEnabled()) {
// Only superuser has permission to do this operation.
- if (!isSuperUser(clientRole, authenticationData)) {
+ if (!isSuperUser(authParams)) {
throw new RestException(Status.UNAUTHORIZED, "This operation requires super-user access");
}
}
@@ -1094,23 +1033,13 @@ public String triggerFunction(final String tenant,
final String input,
final InputStream uploadedInputStream,
final String topic,
- final String clientRole,
- final AuthenticationDataSource clientAuthenticationDataHttps) {
+ final AuthenticationParameters authParams) {
if (!isWorkerServiceAvailable()) {
throwUnavailableException();
}
- try {
- if (!isAuthorizedRole(tenant, namespace, clientRole, clientAuthenticationDataHttps)) {
- log.warn("{}/{}/{} Client [{}] is not authorized to trigger {}", tenant, namespace,
- functionName, clientRole, ComponentTypeUtils.toString(componentType));
- throw new RestException(Status.UNAUTHORIZED, "Client is not authorized to perform operation");
- }
- } catch (PulsarAdminException e) {
- log.error("{}/{}/{} Failed to authorize [{}]", tenant, namespace, functionName, e);
- throw new RestException(Status.INTERNAL_SERVER_ERROR, e.getMessage());
- }
+ throwRestExceptionIfUnauthorizedForNamespace(tenant, namespace, functionName, "trigger", authParams);
// validate parameters
try {
@@ -1224,23 +1153,14 @@ public FunctionState getFunctionState(final String tenant,
final String namespace,
final String functionName,
final String key,
- final String clientRole,
- final AuthenticationDataSource clientAuthenticationDataHttps) {
+ final AuthenticationParameters authParams) {
if (!isWorkerServiceAvailable()) {
throwUnavailableException();
}
- try {
- if (!isAuthorizedRole(tenant, namespace, clientRole, clientAuthenticationDataHttps)) {
- log.warn("{}/{}/{} Client [{}] is not authorized to get state for {}", tenant, namespace,
- functionName, clientRole, ComponentTypeUtils.toString(componentType));
- throw new RestException(Status.UNAUTHORIZED, "Client is not authorized to perform operation");
- }
- } catch (PulsarAdminException e) {
- log.error("{}/{}/{} Failed to authorize [{}]", tenant, namespace, functionName, e);
- throw new RestException(Status.INTERNAL_SERVER_ERROR, e.getMessage());
- }
+ throwRestExceptionIfUnauthorizedForNamespace(tenant, namespace, functionName, "get state for",
+ authParams);
if (null == worker().getStateStoreAdminClient()) {
throwStateStoreUnvailableResponse();
@@ -1310,8 +1230,7 @@ public void putFunctionState(final String tenant,
final String functionName,
final String key,
final FunctionState state,
- final String clientRole,
- final AuthenticationDataSource clientAuthenticationDataHttps) {
+ final AuthenticationParameters authParams) {
if (!isWorkerServiceAvailable()) {
throwUnavailableException();
@@ -1321,16 +1240,8 @@ public void putFunctionState(final String tenant,
throwStateStoreUnvailableResponse();
}
- try {
- if (!isAuthorizedRole(tenant, namespace, clientRole, clientAuthenticationDataHttps)) {
- log.warn("{}/{}/{} Client [{}] is not authorized to put state for {}", tenant, namespace,
- functionName, clientRole, ComponentTypeUtils.toString(componentType));
- throw new RestException(Status.UNAUTHORIZED, "Client is not authorized to perform operation");
- }
- } catch (PulsarAdminException e) {
- log.error("{}/{}/{} Failed to authorize [{}]", tenant, namespace, functionName, e);
- throw new RestException(Status.INTERNAL_SERVER_ERROR, e.getMessage());
- }
+ throwRestExceptionIfUnauthorizedForNamespace(tenant, namespace, functionName, "put state for",
+ authParams);
if (!key.equals(state.getKey())) {
log.error("{}/{}/{} Bad putFunction Request, path key doesn't match key in json", tenant, namespace,
@@ -1386,14 +1297,14 @@ public void putFunctionState(final String tenant,
}
@Override
- public void uploadFunction(final InputStream uploadedInputStream, final String path, String clientRole,
- AuthenticationDataSource authenticationData) {
+ public void uploadFunction(final InputStream uploadedInputStream, final String path,
+ AuthenticationParameters authParams) {
if (!isWorkerServiceAvailable()) {
throwUnavailableException();
}
- if (worker().getWorkerConfig().isAuthorizationEnabled() && !isSuperUser(clientRole, authenticationData)) {
+ if (worker().getWorkerConfig().isAuthorizationEnabled() && !isSuperUser(authParams)) {
throw new RestException(Status.UNAUTHORIZED, "Client is not authorized to perform operation");
}
@@ -1428,23 +1339,13 @@ public void uploadFunction(final InputStream uploadedInputStream, final String p
@Override
public StreamingOutput downloadFunction(String tenant, String namespace, String componentName,
- String clientRole, AuthenticationDataSource clientAuthenticationDataHttps,
- boolean transformFunction) {
+ AuthenticationParameters authParams, boolean transformFunction) {
if (!isWorkerServiceAvailable()) {
throwUnavailableException();
}
- try {
- if (!isAuthorizedRole(tenant, namespace, clientRole, clientAuthenticationDataHttps)) {
- log.warn("{}/{}/{} Client [{}] is not admin and authorized to download package for {} ", tenant,
- namespace,
- componentName, clientRole, ComponentTypeUtils.toString(componentType));
- throw new RestException(Status.UNAUTHORIZED, "Client is not authorized to perform operation");
- }
- } catch (PulsarAdminException e) {
- log.error("{}/{}/{} Failed to authorize [{}]", tenant, namespace, componentName, e);
- throw new RestException(Status.INTERNAL_SERVER_ERROR, e.getMessage());
- }
+ throwRestExceptionIfUnauthorizedForNamespace(tenant, namespace, componentName, "download package for",
+ authParams);
FunctionMetaDataManager functionMetaDataManager = worker().getFunctionMetaDataManager();
if (!functionMetaDataManager.containsFunction(tenant, namespace, componentName)) {
@@ -1529,8 +1430,7 @@ private Path getBuiltinArchivePath(String pkgPath, FunctionDetails.ComponentType
}
@Override
- public StreamingOutput downloadFunction(
- final String path, String clientRole, AuthenticationDataSource clientAuthenticationDataHttps) {
+ public StreamingOutput downloadFunction(final String path, final AuthenticationParameters authParams) {
if (!isWorkerServiceAvailable()) {
throwUnavailableException();
@@ -1544,19 +1444,10 @@ public StreamingOutput downloadFunction(
String namespace = tokens[1];
String componentName = tokens[2];
- try {
- if (!isAuthorizedRole(tenant, namespace, clientRole, clientAuthenticationDataHttps)) {
- log.warn("{}/{}/{} Client [{}] is not admin and authorized to download package for {} ", tenant,
- namespace,
- componentName, clientRole, ComponentTypeUtils.toString(componentType));
- throw new RestException(Status.UNAUTHORIZED, "Client is not authorized to perform operation");
- }
- } catch (PulsarAdminException e) {
- log.error("{}/{}/{} Failed to authorize [{}]", tenant, namespace, componentName, e);
- throw new RestException(Status.INTERNAL_SERVER_ERROR, e.getMessage());
- }
+ throwRestExceptionIfUnauthorizedForNamespace(tenant, namespace, componentName, "download package for",
+ authParams);
} else {
- if (!isSuperUser(clientRole, clientAuthenticationDataHttps)) {
+ if (!isSuperUser(authParams)) {
throw new RestException(Status.UNAUTHORIZED, "Client is not authorized to perform operation");
}
}
@@ -1694,57 +1585,61 @@ public static String createPackagePath(String tenant, String namespace, String f
getUniquePackageName(Codec.encode(fileName)));
}
+ /**
+ * @deprecated use {@link #isAuthorizedRole(String, String, AuthenticationParameters)} instead.
+ */
+ @Deprecated
public boolean isAuthorizedRole(String tenant, String namespace, String clientRole,
AuthenticationDataSource authenticationData) throws PulsarAdminException {
- if (worker().getWorkerConfig().isAuthorizationEnabled()) {
- // skip authorization if client role is super-user
- if (isSuperUser(clientRole, authenticationData)) {
- return true;
- }
-
- if (clientRole != null) {
- try {
- TenantInfoImpl tenantInfo =
- (TenantInfoImpl) worker().getBrokerAdmin().tenants().getTenantInfo(tenant);
- if (tenantInfo != null && worker().getAuthorizationService()
- .isTenantAdmin(tenant, clientRole, tenantInfo, authenticationData).get()) {
- return true;
- }
- } catch (PulsarAdminException.NotFoundException | InterruptedException | ExecutionException e) {
+ AuthenticationParameters authParams = AuthenticationParameters.builder().clientRole(clientRole)
+ .clientAuthenticationDataSource(authenticationData).build();
+ return isAuthorizedRole(tenant, namespace, authParams);
+ }
- }
- }
+ public boolean isAuthorizedRole(String tenant, String namespace,
+ AuthenticationParameters authParams) throws PulsarAdminException {
+ if (worker().getWorkerConfig().isAuthorizationEnabled()) {
+ return allowFunctionOps(NamespaceName.get(tenant, namespace), authParams);
+ } else {
+ return true;
+ }
+ }
- // check if role has permissions granted
- if (clientRole != null && authenticationData != null) {
- return allowFunctionOps(NamespaceName.get(tenant, namespace), clientRole, authenticationData);
- } else {
- return false;
+ public void throwRestExceptionIfUnauthorizedForNamespace(String tenant, String namespace, String componentName,
+ String action, AuthenticationParameters authParams) {
+ try {
+ if (!isAuthorizedRole(tenant, namespace, authParams)) {
+ log.warn("{}/{}/{} Client with role [{}] and originalPrincipal [{}] is not authorized to {} {}",
+ tenant, namespace, componentName, authParams.getClientRole(),
+ authParams.getOriginalPrincipal(), action, ComponentTypeUtils.toString(componentType));
+ throw new RestException(Status.UNAUTHORIZED, "Client is not authorized to perform operation");
}
+ } catch (PulsarAdminException e) {
+ log.error("{}/{}/{} Failed to authorize [{}]", tenant, namespace, componentName, e);
+ throw new RestException(Status.INTERNAL_SERVER_ERROR, e.getMessage());
}
- return true;
}
-
+ @Deprecated
protected void componentStatusRequestValidate(final String tenant, final String namespace,
final String componentName,
final String clientRole,
final AuthenticationDataSource clientAuthenticationDataHttps) {
+ AuthenticationParameters authParams = AuthenticationParameters.builder().clientRole(clientRole)
+ .clientAuthenticationDataSource(clientAuthenticationDataHttps).build();
+ componentStatusRequestValidate(tenant, namespace, componentName, authParams);
+ }
+
+ protected void componentStatusRequestValidate(final String tenant, final String namespace,
+ final String componentName,
+ final AuthenticationParameters authParams) {
if (!isWorkerServiceAvailable()) {
throw new RestException(Status.SERVICE_UNAVAILABLE,
"Function worker service is not done initializing. Please try again in a little while.");
}
- try {
- if (!isAuthorizedRole(tenant, namespace, clientRole, clientAuthenticationDataHttps)) {
- log.warn("{}/{}/{} Client [{}] is not authorized get status for {}", tenant, namespace,
- componentName, clientRole, ComponentTypeUtils.toString(componentType));
- throw new RestException(Status.UNAUTHORIZED, "Client is not authorized to perform operation");
- }
- } catch (PulsarAdminException e) {
- log.error("{}/{}/{} Failed to authorize [{}]", tenant, namespace, componentName, e);
- throw new RestException(Status.INTERNAL_SERVER_ERROR, e.getMessage());
- }
+ throwRestExceptionIfUnauthorizedForNamespace(tenant, namespace, componentName, "get status for",
+ authParams);
// validate parameters
try {
@@ -1773,13 +1668,25 @@ protected void componentStatusRequestValidate(final String tenant, final String
}
}
+ @Deprecated
protected void componentInstanceStatusRequestValidate(final String tenant,
final String namespace,
final String componentName,
final int instanceId,
final String clientRole,
final AuthenticationDataSource clientAuthenticationDataHttps) {
- componentStatusRequestValidate(tenant, namespace, componentName, clientRole, clientAuthenticationDataHttps);
+ AuthenticationParameters authParams = AuthenticationParameters.builder().clientRole(clientRole)
+ .clientAuthenticationDataSource(clientAuthenticationDataHttps).build();
+ componentInstanceStatusRequestValidate(tenant, namespace, componentName, instanceId, authParams);
+ }
+
+ protected void componentInstanceStatusRequestValidate(final String tenant,
+ final String namespace,
+ final String componentName,
+ final int instanceId,
+ final AuthenticationParameters authParams) {
+
+ componentStatusRequestValidate(tenant, namespace, componentName, authParams);
FunctionMetaDataManager functionMetaDataManager = worker().getFunctionMetaDataManager();
FunctionMetaData functionMetaData =
@@ -1794,44 +1701,58 @@ protected void componentInstanceStatusRequestValidate(final String tenant,
}
}
- public boolean isSuperUser(String clientRole, AuthenticationDataSource authenticationData) {
- if (clientRole != null) {
+ public boolean isSuperUser(AuthenticationParameters authParams) {
+ if (authParams.getClientRole() != null) {
try {
- if ((worker().getWorkerConfig().getSuperUserRoles() != null
- && worker().getWorkerConfig().getSuperUserRoles().contains(clientRole))) {
- return true;
- }
- return worker().getAuthorizationService().isSuperUser(clientRole, authenticationData)
- .get(worker().getWorkerConfig().getMetadataStoreOperationTimeoutSeconds(), SECONDS);
+ return worker().getAuthorizationService().isSuperUser(authParams)
+ .get(worker().getWorkerConfig().getMetadataStoreOperationTimeoutSeconds(), SECONDS);
} catch (InterruptedException e) {
- log.warn("Time-out {} sec while checking the role {} is a super user role ",
- worker().getWorkerConfig().getMetadataStoreOperationTimeoutSeconds(), clientRole);
+ log.warn("Time-out {} sec while checking the role {} originalPrincipal {} is a super user role ",
+ worker().getWorkerConfig().getMetadataStoreOperationTimeoutSeconds(),
+ authParams.getClientRole(), authParams.getOriginalPrincipal());
throw new RestException(Status.INTERNAL_SERVER_ERROR, e.getMessage());
} catch (Exception e) {
- log.warn("Admin-client with Role - failed to check the role {} is a super user role {} ", clientRole,
- e.getMessage(), e);
+ log.warn("Failed verifying role {} originalPrincipal {} is a super user role",
+ authParams.getClientRole(), authParams.getOriginalPrincipal(), e);
throw new RestException(Status.INTERNAL_SERVER_ERROR, e.getMessage());
}
}
return false;
}
+ /**
+ * @deprecated use {@link #isSuperUser(AuthenticationParameters)}
+ */
+ @Deprecated
+ public boolean isSuperUser(String clientRole, AuthenticationDataSource authenticationData) {
+ AuthenticationParameters authParams = AuthenticationParameters.builder().clientRole(clientRole)
+ .clientAuthenticationDataSource(authenticationData).build();
+ return isSuperUser(authParams);
+ }
+
+ /**
+ * @deprecated use {@link #isSuperUser(AuthenticationParameters)}
+ */
+ @Deprecated
public boolean allowFunctionOps(NamespaceName namespaceName, String role,
AuthenticationDataSource authenticationData) {
+ AuthenticationParameters authParams = AuthenticationParameters.builder().clientRole(role)
+ .clientAuthenticationDataSource(authenticationData).build();
+ return allowFunctionOps(namespaceName, authParams);
+ }
+
+ public boolean allowFunctionOps(NamespaceName namespaceName, AuthenticationParameters authParams) {
try {
switch (componentType) {
case SINK:
- return worker().getAuthorizationService().allowSinkOpsAsync(
- namespaceName, role, authenticationData)
+ return worker().getAuthorizationService().allowSinkOpsAsync(namespaceName, authParams)
.get(worker().getWorkerConfig().getMetadataStoreOperationTimeoutSeconds(), SECONDS);
case SOURCE:
- return worker().getAuthorizationService().allowSourceOpsAsync(
- namespaceName, role, authenticationData)
+ return worker().getAuthorizationService().allowSourceOpsAsync(namespaceName, authParams)
.get(worker().getWorkerConfig().getMetadataStoreOperationTimeoutSeconds(), SECONDS);
case FUNCTION:
default:
- return worker().getAuthorizationService().allowFunctionOpsAsync(
- namespaceName, role, authenticationData)
+ return worker().getAuthorizationService().allowFunctionOpsAsync(namespaceName, authParams)
.get(worker().getWorkerConfig().getMetadataStoreOperationTimeoutSeconds(), SECONDS);
}
} catch (InterruptedException e) {
@@ -1839,9 +1760,9 @@ public boolean allowFunctionOps(NamespaceName namespaceName, String role,
worker().getWorkerConfig().getMetadataStoreOperationTimeoutSeconds(), namespaceName);
throw new RestException(Status.INTERNAL_SERVER_ERROR, e.getMessage());
} catch (Exception e) {
- log.warn("Admin-client with Role - {} failed to get function permissions for namespace - {}. {}", role,
- namespaceName,
- e.getMessage(), e);
+ log.warn("Admin-client with Role [{}] originalPrincipal [{}] failed to get function permissions for "
+ + "namespace - {}. {}", authParams.getClientRole(),
+ authParams.getOriginalPrincipal(), namespaceName, e.getMessage(), e);
throw new RestException(Status.INTERNAL_SERVER_ERROR, e.getMessage());
}
}
diff --git a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/FunctionsImpl.java b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/FunctionsImpl.java
index b7883e14c91e8..c7967600da5f6 100644
--- a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/FunctionsImpl.java
+++ b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/FunctionsImpl.java
@@ -38,7 +38,7 @@
import javax.ws.rs.core.UriBuilder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
-import org.apache.pulsar.broker.authentication.AuthenticationDataSource;
+import org.apache.pulsar.broker.authentication.AuthenticationParameters;
import org.apache.pulsar.client.admin.PulsarAdminException;
import org.apache.pulsar.common.functions.FunctionConfig;
import org.apache.pulsar.common.functions.FunctionDefinition;
@@ -78,8 +78,7 @@ public void registerFunction(final String tenant,
final FormDataContentDisposition fileDetail,
final String functionPkgUrl,
final FunctionConfig functionConfig,
- final String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps) {
+ final AuthenticationParameters authParams) {
if (!isWorkerServiceAvailable()) {
throwUnavailableException();
@@ -98,16 +97,7 @@ public void registerFunction(final String tenant,
throw new RestException(Response.Status.BAD_REQUEST, "Function config is not provided");
}
- try {
- if (!isAuthorizedRole(tenant, namespace, clientRole, clientAuthenticationDataHttps)) {
- log.error("{}/{}/{} Client [{}] is not authorized to register {}", tenant, namespace,
- functionName, clientRole, ComponentTypeUtils.toString(componentType));
- throw new RestException(Response.Status.UNAUTHORIZED, "Client is not authorized to perform operation");
- }
- } catch (PulsarAdminException e) {
- log.error("{}/{}/{} Failed to authorize [{}]", tenant, namespace, functionName, e);
- throw new RestException(Response.Status.INTERNAL_SERVER_ERROR, e.getMessage());
- }
+ throwRestExceptionIfUnauthorizedForNamespace(tenant, namespace, functionName, "register", authParams);
try {
// Check tenant exists
@@ -124,8 +114,8 @@ public void registerFunction(final String tenant,
}
}
} catch (PulsarAdminException.NotAuthorizedException e) {
- log.error("{}/{}/{} Client [{}] is not authorized to operate {} on tenant", tenant, namespace,
- functionName, clientRole, ComponentTypeUtils.toString(componentType));
+ log.error("{}/{}/{} Client is not authorized to operate {} on tenant", tenant, namespace,
+ functionName, ComponentTypeUtils.toString(componentType));
throw new RestException(Response.Status.UNAUTHORIZED, "Client is not authorized to perform operation");
} catch (PulsarAdminException.NotFoundException e) {
log.error("{}/{}/{} Tenant {} does not exist", tenant, namespace, functionName, tenant);
@@ -193,11 +183,12 @@ public void registerFunction(final String tenant,
worker().getFunctionRuntimeManager()
.getRuntimeFactory()
.getAuthProvider().ifPresent(functionAuthProvider -> {
- if (clientAuthenticationDataHttps != null) {
+ if (authParams.getClientAuthenticationDataSource() != null) {
try {
Optional functionAuthData = functionAuthProvider
- .cacheAuthData(finalFunctionDetails, clientAuthenticationDataHttps);
+ .cacheAuthData(finalFunctionDetails,
+ authParams.getClientAuthenticationDataSource());
functionAuthData.ifPresent(authData -> functionMetaDataBuilder.setFunctionAuthSpec(
Function.FunctionAuthenticationSpec.newBuilder()
@@ -245,8 +236,7 @@ public void updateFunction(final String tenant,
final FormDataContentDisposition fileDetail,
final String functionPkgUrl,
final FunctionConfig functionConfig,
- final String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps,
+ final AuthenticationParameters authParams,
UpdateOptionsImpl updateOptions) {
if (!isWorkerServiceAvailable()) {
@@ -266,17 +256,8 @@ public void updateFunction(final String tenant,
throw new RestException(Response.Status.BAD_REQUEST, "Function config is not provided");
}
- try {
- if (!isAuthorizedRole(tenant, namespace, clientRole, clientAuthenticationDataHttps)) {
- log.error("{}/{}/{} Client [{}] is not authorized to update {}", tenant, namespace,
- functionName, clientRole, ComponentTypeUtils.toString(componentType));
- throw new RestException(Response.Status.UNAUTHORIZED, "Client is not authorized to perform operation");
-
- }
- } catch (PulsarAdminException e) {
- log.error("{}/{}/{} Failed to authorize [{}]", tenant, namespace, functionName, e);
- throw new RestException(Response.Status.INTERNAL_SERVER_ERROR, e.getMessage());
- }
+ throwRestExceptionIfUnauthorizedForNamespace(tenant, namespace, functionName, "update",
+ authParams);
FunctionMetaDataManager functionMetaDataManager = worker().getFunctionMetaDataManager();
@@ -357,7 +338,7 @@ public void updateFunction(final String tenant,
worker().getFunctionRuntimeManager()
.getRuntimeFactory()
.getAuthProvider().ifPresent(functionAuthProvider -> {
- if (clientAuthenticationDataHttps != null && updateOptions
+ if (authParams.getClientAuthenticationDataSource() != null && updateOptions
!= null && updateOptions.isUpdateAuthData()) {
// get existing auth data if it exists
Optional existingFunctionAuthData = Optional.empty();
@@ -369,7 +350,7 @@ public void updateFunction(final String tenant,
try {
Optional newFunctionAuthData = functionAuthProvider
.updateAuthData(finalFunctionDetails, existingFunctionAuthData,
- clientAuthenticationDataHttps);
+ authParams.getClientAuthenticationDataSource());
if (newFunctionAuthData.isPresent()) {
functionMetaDataBuilder.setFunctionAuthSpec(
@@ -597,12 +578,11 @@ public FunctionStatus.FunctionInstanceStatus.FunctionInstanceStatusData getFunct
final String componentName,
final String instanceId,
final URI uri,
- final String clientRole,
- final AuthenticationDataSource clientAuthenticationDataHttps) {
+ final AuthenticationParameters authParams) {
// validate parameters
componentInstanceStatusRequestValidate(tenant, namespace, componentName, Integer.parseInt(instanceId),
- clientRole, clientAuthenticationDataHttps);
+ authParams);
FunctionStatus.FunctionInstanceStatus.FunctionInstanceStatusData functionInstanceStatusData;
try {
@@ -632,11 +612,10 @@ public FunctionStatus getFunctionStatus(final String tenant,
final String namespace,
final String componentName,
final URI uri,
- final String clientRole,
- final AuthenticationDataSource clientAuthenticationDataHttps) {
+ final AuthenticationParameters authParams) {
// validate parameters
- componentStatusRequestValidate(tenant, namespace, componentName, clientRole, clientAuthenticationDataHttps);
+ componentStatusRequestValidate(tenant, namespace, componentName, authParams);
FunctionStatus functionStatus;
try {
@@ -658,17 +637,18 @@ public void updateFunctionOnWorkerLeader(final String tenant,
final InputStream uploadedInputStream,
final boolean delete,
URI uri,
- final String clientRole,
- AuthenticationDataSource authenticationData) {
+ final AuthenticationParameters authParams) {
if (!isWorkerServiceAvailable()) {
throwUnavailableException();
}
if (worker().getWorkerConfig().isAuthorizationEnabled()) {
- if (!isSuperUser(clientRole, authenticationData)) {
- log.error("{}/{}/{} Client [{}] is not superuser to update on worker leader {}", tenant, namespace,
- functionName, clientRole, ComponentTypeUtils.toString(componentType));
+ if (!isSuperUser(authParams)) {
+ log.error("{}/{}/{} Client with role [{}] and originalPrincipal [{}] is not superuser to update on"
+ + " worker leader {}", tenant, namespace, functionName, authParams.getClientRole(),
+ authParams.getClientAuthenticationDataSource(),
+ ComponentTypeUtils.toString(componentType));
throw new RestException(Response.Status.UNAUTHORIZED, "Client is not authorized to perform operation");
}
}
@@ -713,26 +693,26 @@ public void updateFunctionOnWorkerLeader(final String tenant,
}
@Override
- public void reloadBuiltinFunctions(String clientRole, AuthenticationDataSource authenticationData)
+ public void reloadBuiltinFunctions(AuthenticationParameters authParams)
throws IOException {
if (!isWorkerServiceAvailable()) {
throwUnavailableException();
}
- if (worker().getWorkerConfig().isAuthorizationEnabled() && !isSuperUser(clientRole, authenticationData)) {
+ if (worker().getWorkerConfig().isAuthorizationEnabled()
+ && !isSuperUser(authParams)) {
throw new RestException(Response.Status.UNAUTHORIZED, "Client is not authorized to perform operation");
}
worker().getFunctionsManager().reloadFunctions(worker().getWorkerConfig());
}
@Override
- public List getBuiltinFunctions(String clientRole,
- AuthenticationDataSource authenticationData) {
+ public List getBuiltinFunctions(AuthenticationParameters authParams) {
if (!isWorkerServiceAvailable()) {
throwUnavailableException();
}
- if (worker().getWorkerConfig().isAuthorizationEnabled() && !isSuperUser(clientRole, authenticationData)) {
+ if (worker().getWorkerConfig().isAuthorizationEnabled() && !isSuperUser(authParams)) {
throw new RestException(Response.Status.UNAUTHORIZED, "Client is not authorized to perform operation");
}
return this.worker().getFunctionsManager().getFunctionDefinitions();
diff --git a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/FunctionsImplV2.java b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/FunctionsImplV2.java
index 7b7f84aa82823..059db75542d59 100644
--- a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/FunctionsImplV2.java
+++ b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/FunctionsImplV2.java
@@ -28,6 +28,7 @@
import java.util.stream.Collectors;
import javax.ws.rs.core.Response;
import lombok.extern.slf4j.Slf4j;
+import org.apache.pulsar.broker.authentication.AuthenticationParameters;
import org.apache.pulsar.common.functions.FunctionConfig;
import org.apache.pulsar.common.functions.FunctionState;
import org.apache.pulsar.common.io.ConnectorDefinition;
@@ -59,11 +60,11 @@ public FunctionsImplV2(FunctionsImpl delegate) {
@Override
public Response getFunctionInfo(final String tenant, final String namespace,
- final String functionName, String clientRole)
+ final String functionName, AuthenticationParameters authParams)
throws IOException {
// run just for parameter checks
- delegate.getFunctionInfo(tenant, namespace, functionName, clientRole, null);
+ delegate.getFunctionInfo(tenant, namespace, functionName, authParams);
FunctionMetaDataManager functionMetaDataManager = delegate.worker().getFunctionMetaDataManager();
@@ -75,11 +76,12 @@ public Response getFunctionInfo(final String tenant, final String namespace,
@Override
public Response getFunctionInstanceStatus(final String tenant, final String namespace, final String functionName,
- final String instanceId, URI uri, String clientRole) throws IOException {
+ final String instanceId, URI uri,
+ AuthenticationParameters authParams) throws IOException {
org.apache.pulsar.common.policies.data.FunctionStatus.FunctionInstanceStatus.FunctionInstanceStatusData
functionInstanceStatus = delegate.getFunctionInstanceStatus(tenant, namespace,
- functionName, instanceId, uri, clientRole, null);
+ functionName, instanceId, uri, authParams);
String jsonResponse = FunctionCommon.printJson(toProto(functionInstanceStatus, instanceId));
return Response.status(Response.Status.OK).entity(jsonResponse).build();
@@ -87,10 +89,10 @@ public Response getFunctionInstanceStatus(final String tenant, final String name
@Override
public Response getFunctionStatusV2(String tenant, String namespace, String functionName,
- URI requestUri, String clientRole) throws
+ URI requestUri, AuthenticationParameters authParams) throws
IOException {
FunctionStatus functionStatus = delegate.getFunctionStatus(tenant, namespace,
- functionName, requestUri, clientRole, null);
+ functionName, requestUri, authParams);
InstanceCommunication.FunctionStatusList.Builder functionStatusList =
InstanceCommunication.FunctionStatusList.newBuilder();
functionStatus.instances.forEach(functionInstanceStatus -> functionStatusList.addFunctionStatusList(
@@ -103,7 +105,7 @@ public Response getFunctionStatusV2(String tenant, String namespace, String func
@Override
public Response registerFunction(String tenant, String namespace, String functionName, InputStream
uploadedInputStream, FormDataContentDisposition fileDetail, String functionPkgUrl, String
- functionDetailsJson, String clientRole) {
+ functionDetailsJson, AuthenticationParameters authParams) {
Function.FunctionDetails.Builder functionDetailsBuilder = Function.FunctionDetails.newBuilder();
try {
@@ -114,14 +116,15 @@ public Response registerFunction(String tenant, String namespace, String functio
FunctionConfig functionConfig = FunctionConfigUtils.convertFromDetails(functionDetailsBuilder.build());
delegate.registerFunction(tenant, namespace, functionName, uploadedInputStream, fileDetail,
- functionPkgUrl, functionConfig, clientRole, null);
+ functionPkgUrl, functionConfig, authParams);
return Response.ok().build();
}
@Override
public Response updateFunction(String tenant, String namespace, String functionName,
InputStream uploadedInputStream, FormDataContentDisposition fileDetail,
- String functionPkgUrl, String functionDetailsJson, String clientRole) {
+ String functionPkgUrl, String functionDetailsJson,
+ AuthenticationParameters authParams) {
Function.FunctionDetails.Builder functionDetailsBuilder = Function.FunctionDetails.newBuilder();
try {
@@ -132,35 +135,36 @@ public Response updateFunction(String tenant, String namespace, String functionN
FunctionConfig functionConfig = FunctionConfigUtils.convertFromDetails(functionDetailsBuilder.build());
delegate.updateFunction(tenant, namespace, functionName, uploadedInputStream, fileDetail,
- functionPkgUrl, functionConfig, clientRole, null, null);
+ functionPkgUrl, functionConfig, authParams, null);
return Response.ok().build();
}
@Override
- public Response deregisterFunction(String tenant, String namespace, String functionName, String clientAppId) {
- delegate.deregisterFunction(tenant, namespace, functionName, clientAppId, null);
+ public Response deregisterFunction(String tenant, String namespace, String functionName,
+ AuthenticationParameters authParams) {
+ delegate.deregisterFunction(tenant, namespace, functionName, authParams);
return Response.ok().build();
}
@Override
- public Response listFunctions(String tenant, String namespace, String clientRole) {
- Collection functionStateList = delegate.listFunctions(tenant, namespace, clientRole, null);
+ public Response listFunctions(String tenant, String namespace, AuthenticationParameters authParams) {
+ Collection functionStateList = delegate.listFunctions(tenant, namespace, authParams);
return Response.status(Response.Status.OK).entity(new Gson().toJson(functionStateList.toArray())).build();
}
@Override
public Response triggerFunction(String tenant, String namespace, String functionName, String triggerValue,
- InputStream triggerStream, String topic, String clientRole) {
+ InputStream triggerStream, String topic, AuthenticationParameters authParams) {
String result = delegate.triggerFunction(tenant, namespace, functionName,
- triggerValue, triggerStream, topic, clientRole, null);
+ triggerValue, triggerStream, topic, authParams);
return Response.status(Response.Status.OK).entity(result).build();
}
@Override
public Response getFunctionState(String tenant, String namespace, String functionName,
- String key, String clientRole) {
+ String key, AuthenticationParameters authParams) {
FunctionState functionState = delegate.getFunctionState(
- tenant, namespace, functionName, key, clientRole, null);
+ tenant, namespace, functionName, key, authParams);
String value;
if (functionState.getNumberValue() != null) {
@@ -175,39 +179,41 @@ public Response getFunctionState(String tenant, String namespace, String functio
@Override
public Response restartFunctionInstance(String tenant, String namespace, String functionName, String instanceId, URI
- uri, String clientRole) {
- delegate.restartFunctionInstance(tenant, namespace, functionName, instanceId, uri, clientRole, null);
+ uri, AuthenticationParameters authParams) {
+ delegate.restartFunctionInstance(tenant, namespace, functionName, instanceId, uri, authParams);
return Response.ok().build();
}
@Override
- public Response restartFunctionInstances(String tenant, String namespace, String functionName, String clientRole) {
- delegate.restartFunctionInstances(tenant, namespace, functionName, clientRole, null);
+ public Response restartFunctionInstances(String tenant, String namespace, String functionName,
+ AuthenticationParameters authParams) {
+ delegate.restartFunctionInstances(tenant, namespace, functionName, authParams);
return Response.ok().build();
}
@Override
public Response stopFunctionInstance(String tenant, String namespace, String functionName, String instanceId, URI
- uri, String clientRole) {
- delegate.stopFunctionInstance(tenant, namespace, functionName, instanceId, uri, clientRole, null);
+ uri, AuthenticationParameters authParams) {
+ delegate.stopFunctionInstance(tenant, namespace, functionName, instanceId, uri, authParams);
return Response.ok().build();
}
@Override
- public Response stopFunctionInstances(String tenant, String namespace, String functionName, String clientRole) {
- delegate.stopFunctionInstances(tenant, namespace, functionName, clientRole, null);
+ public Response stopFunctionInstances(String tenant, String namespace, String functionName,
+ AuthenticationParameters authParams) {
+ delegate.stopFunctionInstances(tenant, namespace, functionName, authParams);
return Response.ok().build();
}
@Override
- public Response uploadFunction(InputStream uploadedInputStream, String path, String clientRole) {
- delegate.uploadFunction(uploadedInputStream, path, clientRole, null);
+ public Response uploadFunction(InputStream uploadedInputStream, String path, AuthenticationParameters authParams) {
+ delegate.uploadFunction(uploadedInputStream, path, authParams);
return Response.ok().build();
}
@Override
- public Response downloadFunction(String path, String clientRole) {
- return Response.status(Response.Status.OK).entity(delegate.downloadFunction(path, clientRole, null)).build();
+ public Response downloadFunction(String path, AuthenticationParameters authParams) {
+ return Response.status(Response.Status.OK).entity(delegate.downloadFunction(path, authParams)).build();
}
@Override
diff --git a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/SinksImpl.java b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/SinksImpl.java
index fff376c5dcca1..98450c4a0b5d0 100644
--- a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/SinksImpl.java
+++ b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/SinksImpl.java
@@ -38,7 +38,7 @@
import javax.ws.rs.core.Response;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
-import org.apache.pulsar.broker.authentication.AuthenticationDataSource;
+import org.apache.pulsar.broker.authentication.AuthenticationParameters;
import org.apache.pulsar.client.admin.PulsarAdminException;
import org.apache.pulsar.common.functions.UpdateOptionsImpl;
import org.apache.pulsar.common.functions.Utils;
@@ -77,8 +77,7 @@ public void registerSink(final String tenant,
final FormDataContentDisposition fileDetail,
final String sinkPkgUrl,
final SinkConfig sinkConfig,
- final String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps) {
+ final AuthenticationParameters authParams) {
if (!isWorkerServiceAvailable()) {
throwUnavailableException();
@@ -97,16 +96,7 @@ public void registerSink(final String tenant,
throw new RestException(Response.Status.BAD_REQUEST, "Sink config is not provided");
}
- try {
- if (!isAuthorizedRole(tenant, namespace, clientRole, clientAuthenticationDataHttps)) {
- log.warn("{}/{}/{} Client [{}] is not authorized to register {}", tenant, namespace,
- sinkName, clientRole, ComponentTypeUtils.toString(componentType));
- throw new RestException(Response.Status.UNAUTHORIZED, "Client is not authorized to perform operation");
- }
- } catch (PulsarAdminException e) {
- log.error("{}/{}/{} Failed to authorize [{}]", tenant, namespace, sinkName, e);
- throw new RestException(Response.Status.INTERNAL_SERVER_ERROR, e.getMessage());
- }
+ throwRestExceptionIfUnauthorizedForNamespace(tenant, namespace, sinkName, "register", authParams);
try {
// Check tenant exists
@@ -123,8 +113,8 @@ public void registerSink(final String tenant,
}
}
} catch (PulsarAdminException.NotAuthorizedException e) {
- log.error("{}/{}/{} Client [{}] is not authorized to operate {} on tenant", tenant, namespace,
- sinkName, clientRole, ComponentTypeUtils.toString(componentType));
+ log.error("{}/{}/{} Client is not authorized to operate {} on tenant", tenant, namespace,
+ sinkName, ComponentTypeUtils.toString(componentType));
throw new RestException(Response.Status.UNAUTHORIZED, "Client is not authorized to perform operation");
} catch (PulsarAdminException.NotFoundException e) {
log.error("{}/{}/{} Tenant {} does not exist", tenant, namespace, sinkName, tenant);
@@ -193,11 +183,12 @@ public void registerSink(final String tenant,
worker().getFunctionRuntimeManager()
.getRuntimeFactory()
.getAuthProvider().ifPresent(functionAuthProvider -> {
- if (clientAuthenticationDataHttps != null) {
+ if (authParams.getClientAuthenticationDataSource() != null) {
try {
Optional functionAuthData = functionAuthProvider
- .cacheAuthData(finalFunctionDetails, clientAuthenticationDataHttps);
+ .cacheAuthData(finalFunctionDetails,
+ authParams.getClientAuthenticationDataSource());
functionAuthData.ifPresent(authData -> functionMetaDataBuilder.setFunctionAuthSpec(
Function.FunctionAuthenticationSpec.newBuilder()
@@ -251,8 +242,7 @@ public void updateSink(final String tenant,
final FormDataContentDisposition fileDetail,
final String sinkPkgUrl,
final SinkConfig sinkConfig,
- final String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps,
+ final AuthenticationParameters authParams,
UpdateOptionsImpl updateOptions) {
if (!isWorkerServiceAvailable()) {
@@ -272,17 +262,7 @@ public void updateSink(final String tenant,
throw new RestException(Response.Status.BAD_REQUEST, "Sink config is not provided");
}
- try {
- if (!isAuthorizedRole(tenant, namespace, clientRole, clientAuthenticationDataHttps)) {
- log.warn("{}/{}/{} Client [{}] is not authorized to update {}", tenant, namespace,
- sinkName, clientRole, ComponentTypeUtils.toString(componentType));
- throw new RestException(Response.Status.UNAUTHORIZED, "Client is not authorized to perform operation");
-
- }
- } catch (PulsarAdminException e) {
- log.error("{}/{}/{} Failed to authorize [{}]", tenant, namespace, sinkName, e);
- throw new RestException(Response.Status.INTERNAL_SERVER_ERROR, e.getMessage());
- }
+ throwRestExceptionIfUnauthorizedForNamespace(tenant, namespace, sinkName, "update", authParams);
FunctionMetaDataManager functionMetaDataManager = worker().getFunctionMetaDataManager();
@@ -363,7 +343,7 @@ public void updateSink(final String tenant,
worker().getFunctionRuntimeManager()
.getRuntimeFactory()
.getAuthProvider().ifPresent(functionAuthProvider -> {
- if (clientAuthenticationDataHttps != null && updateOptions != null
+ if (authParams.getClientAuthenticationDataSource() != null && updateOptions != null
&& updateOptions.isUpdateAuthData()) {
// get existing auth data if it exists
Optional existingFunctionAuthData = Optional.empty();
@@ -375,7 +355,7 @@ public void updateSink(final String tenant,
try {
Optional newFunctionAuthData = functionAuthProvider
.updateAuthData(finalFunctionDetails, existingFunctionAuthData,
- clientAuthenticationDataHttps);
+ authParams.getClientAuthenticationDataSource());
if (newFunctionAuthData.isPresent()) {
functionMetaDataBuilder.setFunctionAuthSpec(
@@ -629,12 +609,11 @@ private ExceptionInformation getExceptionInformation(InstanceCommunication.Funct
final String sinkName,
final String instanceId,
final URI uri,
- final String clientRole,
- final AuthenticationDataSource clientAuthenticationDataHttps) {
+ final AuthenticationParameters authParams) {
// validate parameters
- componentInstanceStatusRequestValidate(tenant, namespace, sinkName, Integer.parseInt(instanceId), clientRole,
- clientAuthenticationDataHttps);
+ componentInstanceStatusRequestValidate(tenant, namespace, sinkName, Integer.parseInt(instanceId),
+ authParams);
SinkStatus.SinkInstanceStatus.SinkInstanceStatusData sinkInstanceStatusData;
@@ -655,11 +634,10 @@ public SinkStatus getSinkStatus(final String tenant,
final String namespace,
final String componentName,
final URI uri,
- final String clientRole,
- final AuthenticationDataSource clientAuthenticationDataHttps) {
+ final AuthenticationParameters authParams) {
// validate parameters
- componentStatusRequestValidate(tenant, namespace, componentName, clientRole, clientAuthenticationDataHttps);
+ componentStatusRequestValidate(tenant, namespace, componentName, authParams);
SinkStatus sinkStatus;
try {
@@ -677,38 +655,12 @@ public SinkStatus getSinkStatus(final String tenant,
@Override
public SinkConfig getSinkInfo(final String tenant,
final String namespace,
- final String componentName) {
-
- if (!isWorkerServiceAvailable()) {
- throwUnavailableException();
- }
-
- // validate parameters
- try {
- validateGetFunctionRequestParams(tenant, namespace, componentName, componentType);
- } catch (IllegalArgumentException e) {
- log.error("Invalid get {} request @ /{}/{}/{}", ComponentTypeUtils.toString(componentType), tenant,
- namespace, componentName, e);
- throw new RestException(Response.Status.BAD_REQUEST, e.getMessage());
- }
-
- FunctionMetaDataManager functionMetaDataManager = worker().getFunctionMetaDataManager();
- if (!functionMetaDataManager.containsFunction(tenant, namespace, componentName)) {
- log.error("{} does not exist @ /{}/{}/{}", ComponentTypeUtils.toString(componentType), tenant, namespace,
- componentName);
- throw new RestException(Response.Status.NOT_FOUND,
- String.format(ComponentTypeUtils.toString(componentType) + " %s doesn't exist", componentName));
- }
+ final String componentName,
+ final AuthenticationParameters authParams) {
+ componentStatusRequestValidate(tenant, namespace, componentName, authParams);
Function.FunctionMetaData functionMetaData =
- functionMetaDataManager.getFunctionMetaData(tenant, namespace, componentName);
- if (!InstanceUtils.calculateSubjectType(functionMetaData.getFunctionDetails()).equals(componentType)) {
- log.error("{}/{}/{} is not a {}", tenant, namespace, componentName,
- ComponentTypeUtils.toString(componentType));
- throw new RestException(Response.Status.NOT_FOUND,
- String.format(ComponentTypeUtils.toString(componentType) + " %s doesn't exist", componentName));
- }
- SinkConfig config = SinkConfigUtils.convertFromDetails(functionMetaData.getFunctionDetails());
- return config;
+ worker().getFunctionMetaDataManager().getFunctionMetaData(tenant, namespace, componentName);
+ return SinkConfigUtils.convertFromDetails(functionMetaData.getFunctionDetails());
}
@Override
diff --git a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/SourcesImpl.java b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/SourcesImpl.java
index 2c5921bf7ea9d..876c7e7572e78 100644
--- a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/SourcesImpl.java
+++ b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/SourcesImpl.java
@@ -37,7 +37,7 @@
import javax.ws.rs.core.Response;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
-import org.apache.pulsar.broker.authentication.AuthenticationDataSource;
+import org.apache.pulsar.broker.authentication.AuthenticationParameters;
import org.apache.pulsar.client.admin.PulsarAdminException;
import org.apache.pulsar.common.functions.UpdateOptionsImpl;
import org.apache.pulsar.common.functions.Utils;
@@ -76,8 +76,7 @@ public void registerSource(final String tenant,
final FormDataContentDisposition fileDetail,
final String sourcePkgUrl,
final SourceConfig sourceConfig,
- final String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps) {
+ final AuthenticationParameters authParams) {
if (!isWorkerServiceAvailable()) {
throwUnavailableException();
@@ -96,16 +95,7 @@ public void registerSource(final String tenant,
throw new RestException(Response.Status.BAD_REQUEST, "Source config is not provided");
}
- try {
- if (!isAuthorizedRole(tenant, namespace, clientRole, clientAuthenticationDataHttps)) {
- log.warn("{}/{}/{} Client [{}] is not authorized to register {}", tenant, namespace,
- sourceName, clientRole, ComponentTypeUtils.toString(componentType));
- throw new RestException(Response.Status.UNAUTHORIZED, "Client is not authorized to perform operation");
- }
- } catch (PulsarAdminException e) {
- log.error("{}/{}/{} Failed to authorize [{}]", tenant, namespace, sourceName, e);
- throw new RestException(Response.Status.INTERNAL_SERVER_ERROR, e.getMessage());
- }
+ throwRestExceptionIfUnauthorizedForNamespace(tenant, namespace, sourceName, "register", authParams);
try {
// Check tenant exists
@@ -122,8 +112,8 @@ public void registerSource(final String tenant,
}
}
} catch (PulsarAdminException.NotAuthorizedException e) {
- log.error("{}/{}/{} Client [{}] is not authorized to operate {} on tenant", tenant, namespace,
- sourceName, clientRole, ComponentTypeUtils.toString(componentType));
+ log.error("{}/{}/{} Client is not authorized to operate {} on tenant", tenant, namespace,
+ sourceName, ComponentTypeUtils.toString(componentType));
throw new RestException(Response.Status.UNAUTHORIZED, "Client is not authorized to perform operation");
} catch (PulsarAdminException.NotFoundException e) {
log.error("{}/{}/{} Tenant {} does not exist", tenant, namespace, sourceName, tenant);
@@ -193,11 +183,12 @@ public void registerSource(final String tenant,
worker().getFunctionRuntimeManager()
.getRuntimeFactory()
.getAuthProvider().ifPresent(functionAuthProvider -> {
- if (clientAuthenticationDataHttps != null) {
+ if (authParams.getClientAuthenticationDataSource() != null) {
try {
Optional functionAuthData = functionAuthProvider
- .cacheAuthData(finalFunctionDetails, clientAuthenticationDataHttps);
+ .cacheAuthData(finalFunctionDetails,
+ authParams.getClientAuthenticationDataSource());
functionAuthData.ifPresent(authData -> functionMetaDataBuilder.setFunctionAuthSpec(
Function.FunctionAuthenticationSpec.newBuilder()
@@ -245,8 +236,7 @@ public void updateSource(final String tenant,
final FormDataContentDisposition fileDetail,
final String sourcePkgUrl,
final SourceConfig sourceConfig,
- final String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps,
+ final AuthenticationParameters authParams,
UpdateOptionsImpl updateOptions) {
if (!isWorkerServiceAvailable()) {
@@ -266,17 +256,7 @@ public void updateSource(final String tenant,
throw new RestException(Response.Status.BAD_REQUEST, "Source config is not provided");
}
- try {
- if (!isAuthorizedRole(tenant, namespace, clientRole, clientAuthenticationDataHttps)) {
- log.warn("{}/{}/{} Client [{}] is not authorized to update {}", tenant, namespace,
- sourceName, clientRole, ComponentTypeUtils.toString(componentType));
- throw new RestException(Response.Status.UNAUTHORIZED, "Client is not authorized to perform operation");
-
- }
- } catch (PulsarAdminException e) {
- log.error("{}/{}/{} Failed to authorize [{}]", tenant, namespace, sourceName, e);
- throw new RestException(Response.Status.INTERNAL_SERVER_ERROR, e.getMessage());
- }
+ throwRestExceptionIfUnauthorizedForNamespace(tenant, namespace, sourceName, "update", authParams);
FunctionMetaDataManager functionMetaDataManager = worker().getFunctionMetaDataManager();
@@ -357,7 +337,7 @@ public void updateSource(final String tenant,
worker().getFunctionRuntimeManager()
.getRuntimeFactory()
.getAuthProvider().ifPresent(functionAuthProvider -> {
- if (clientAuthenticationDataHttps != null && updateOptions != null
+ if (authParams.getClientAuthenticationDataSource() != null && updateOptions != null
&& updateOptions.isUpdateAuthData()) {
// get existing auth data if it exists
Optional existingFunctionAuthData = Optional.empty();
@@ -369,7 +349,7 @@ public void updateSource(final String tenant,
try {
Optional newFunctionAuthData = functionAuthProvider
.updateAuthData(finalFunctionDetails, existingFunctionAuthData,
- clientAuthenticationDataHttps);
+ authParams.getClientAuthenticationDataSource());
if (newFunctionAuthData.isPresent()) {
functionMetaDataBuilder.setFunctionAuthSpec(
@@ -591,10 +571,10 @@ public SourceStatus emptyStatus(final int parallelism) {
public SourceStatus getSourceStatus(final String tenant,
final String namespace,
final String componentName,
- final URI uri, final String clientRole,
- final AuthenticationDataSource clientAuthenticationDataHttps) {
+ final URI uri,
+ final AuthenticationParameters authParams) {
// validate parameters
- componentStatusRequestValidate(tenant, namespace, componentName, clientRole, clientAuthenticationDataHttps);
+ componentStatusRequestValidate(tenant, namespace, componentName, authParams);
SourceStatus sourceStatus;
try {
@@ -616,11 +596,9 @@ public SourceStatus getSourceStatus(final String tenant,
final String sourceName,
final String instanceId,
final URI uri,
- final String clientRole,
- final AuthenticationDataSource clientAuthenticationDataHttps) {
+ final AuthenticationParameters authParams) {
// validate parameters
- componentInstanceStatusRequestValidate(tenant, namespace, sourceName, Integer.parseInt(instanceId), clientRole,
- clientAuthenticationDataHttps);
+ componentInstanceStatusRequestValidate(tenant, namespace, sourceName, Integer.parseInt(instanceId), authParams);
SourceStatus.SourceInstanceStatus.SourceInstanceStatusData sourceInstanceStatusData;
try {
@@ -638,38 +616,12 @@ public SourceStatus getSourceStatus(final String tenant,
@Override
public SourceConfig getSourceInfo(final String tenant,
final String namespace,
- final String componentName) {
-
- if (!isWorkerServiceAvailable()) {
- throwUnavailableException();
- }
-
- // validate parameters
- try {
- validateGetFunctionRequestParams(tenant, namespace, componentName, componentType);
- } catch (IllegalArgumentException e) {
- log.error("Invalid get {} request @ /{}/{}/{}", ComponentTypeUtils.toString(componentType), tenant,
- namespace, componentName, e);
- throw new RestException(Response.Status.BAD_REQUEST, e.getMessage());
- }
-
- FunctionMetaDataManager functionMetaDataManager = worker().getFunctionMetaDataManager();
- if (!functionMetaDataManager.containsFunction(tenant, namespace, componentName)) {
- log.error("{} does not exist @ /{}/{}/{}", ComponentTypeUtils.toString(componentType), tenant, namespace,
- componentName);
- throw new RestException(Response.Status.NOT_FOUND,
- String.format(ComponentTypeUtils.toString(componentType) + " %s doesn't exist", componentName));
- }
+ final String componentName,
+ final AuthenticationParameters authParams) {
+ componentStatusRequestValidate(tenant, namespace, componentName, authParams);
Function.FunctionMetaData functionMetaData =
- functionMetaDataManager.getFunctionMetaData(tenant, namespace, componentName);
- if (!InstanceUtils.calculateSubjectType(functionMetaData.getFunctionDetails()).equals(componentType)) {
- log.error("{}/{}/{} is not a {}", tenant, namespace, componentName,
- ComponentTypeUtils.toString(componentType));
- throw new RestException(Response.Status.NOT_FOUND,
- String.format(ComponentTypeUtils.toString(componentType) + " %s doesn't exist", componentName));
- }
- SourceConfig config = SourceConfigUtils.convertFromDetails(functionMetaData.getFunctionDetails());
- return config;
+ worker().getFunctionMetaDataManager().getFunctionMetaData(tenant, namespace, componentName);
+ return SourceConfigUtils.convertFromDetails(functionMetaData.getFunctionDetails());
}
@Override
diff --git a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/WorkerImpl.java b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/WorkerImpl.java
index 364c3ec1ab104..0b77be4ab0212 100644
--- a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/WorkerImpl.java
+++ b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/WorkerImpl.java
@@ -18,6 +18,7 @@
*/
package org.apache.pulsar.functions.worker.rest.api;
+import static java.util.concurrent.TimeUnit.SECONDS;
import static org.apache.pulsar.functions.worker.rest.RestUtils.throwUnavailableException;
import java.io.IOException;
import java.net.URI;
@@ -27,12 +28,15 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeoutException;
import java.util.function.Supplier;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriBuilder;
import lombok.extern.slf4j.Slf4j;
+import org.apache.pulsar.broker.authentication.AuthenticationParameters;
import org.apache.pulsar.client.admin.LongRunningProcessStatus;
import org.apache.pulsar.common.functions.WorkerInfo;
import org.apache.pulsar.common.io.ConnectorDefinition;
@@ -77,29 +81,24 @@ private boolean isWorkerServiceAvailable() {
}
@Override
- public List getCluster(String clientRole) {
+ public List getCluster(AuthenticationParameters authParams) {
if (!isWorkerServiceAvailable()) {
throwUnavailableException();
}
- if (worker().getWorkerConfig().isAuthorizationEnabled() && !isSuperUser(clientRole)) {
- throw new RestException(Status.UNAUTHORIZED, "Client is not authorized to perform operation");
- }
+ throwIfNotSuperUser(authParams, "get cluster");
List workers = worker().getMembershipManager().getCurrentMembership();
return workers;
}
@Override
- public WorkerInfo getClusterLeader(String clientRole) {
+ public WorkerInfo getClusterLeader(AuthenticationParameters authParams) {
if (!isWorkerServiceAvailable()) {
throwUnavailableException();
}
- if (worker().getWorkerConfig().isAuthorizationEnabled() && !isSuperUser(clientRole)) {
- log.error("Client [{}] is not authorized to get cluster leader", clientRole);
- throw new RestException(Status.UNAUTHORIZED, "Client is not authorized to perform operation");
- }
+ throwIfNotSuperUser(authParams, "get cluster leader");
MembershipManager membershipManager = worker().getMembershipManager();
WorkerInfo leader = membershipManager.getLeader();
@@ -112,15 +111,12 @@ public WorkerInfo getClusterLeader(String clientRole) {
}
@Override
- public Map> getAssignments(String clientRole) {
+ public Map> getAssignments(AuthenticationParameters authParams) {
if (!isWorkerServiceAvailable()) {
throwUnavailableException();
}
- if (worker().getWorkerConfig().isAuthorizationEnabled() && !isSuperUser(clientRole)) {
- log.error("Client [{}] is not authorized to get cluster assignments", clientRole);
- throw new RestException(Status.UNAUTHORIZED, "Client is not authorized to perform operation");
- }
+ throwIfNotSuperUser(authParams, "get cluster assignments");
FunctionRuntimeManager functionRuntimeManager = worker().getFunctionRuntimeManager();
Map> assignments = functionRuntimeManager.getCurrentAssignments();
@@ -131,33 +127,41 @@ public Map> getAssignments(String clientRole) {
return ret;
}
- private boolean isSuperUser(final String clientRole) {
- return clientRole != null && worker().getWorkerConfig().getSuperUserRoles().contains(clientRole);
+ private void throwIfNotSuperUser(AuthenticationParameters authParams, String action) {
+ if (worker().getWorkerConfig().isAuthorizationEnabled()) {
+ try {
+ if (authParams.getClientRole() == null || !worker().getAuthorizationService().isSuperUser(authParams)
+ .get(worker().getWorkerConfig().getMetadataStoreOperationTimeoutSeconds(), SECONDS)) {
+ log.error("Client with role [{}] and originalPrincipal [{}] is not authorized to {}",
+ authParams.getClientRole(), authParams.getOriginalPrincipal(), action);
+ throw new RestException(Status.UNAUTHORIZED, "Client is not authorized to perform operation");
+ }
+ } catch (ExecutionException | TimeoutException | InterruptedException e) {
+ log.warn("Time-out {} sec while checking the role {} originalPrincipal {} is a super user role ",
+ worker().getWorkerConfig().getMetadataStoreOperationTimeoutSeconds(),
+ authParams.getClientRole(), authParams.getOriginalPrincipal());
+ throw new RestException(Status.INTERNAL_SERVER_ERROR, e.getMessage());
+ }
+ }
}
@Override
- public List getWorkerMetrics(final String clientRole) {
+ public List getWorkerMetrics(final AuthenticationParameters authParams) {
if (!isWorkerServiceAvailable() || worker().getMetricsGenerator() == null) {
throwUnavailableException();
}
-
- if (worker().getWorkerConfig().isAuthorizationEnabled() && !isSuperUser(clientRole)) {
- log.error("Client [{}] is not authorized to get worker stats", clientRole);
- throw new RestException(Status.UNAUTHORIZED, "Client is not authorized to perform operation");
- }
+ throwIfNotSuperUser(authParams, "get worker stats");
return worker().getMetricsGenerator().generate();
}
@Override
- public List getFunctionsMetrics(String clientRole) throws IOException {
+ public List getFunctionsMetrics(AuthenticationParameters authParams)
+ throws IOException {
if (!isWorkerServiceAvailable()) {
throwUnavailableException();
}
- if (worker().getWorkerConfig().isAuthorizationEnabled() && !isSuperUser(clientRole)) {
- log.error("Client [{}] is not authorized to get function stats", clientRole);
- throw new RestException(Status.UNAUTHORIZED, "Client is not authorized to perform operation");
- }
+ throwIfNotSuperUser(authParams, "get function stats");
Map functionRuntimes = worker().getFunctionRuntimeManager()
.getFunctionRuntimeInfos();
@@ -196,28 +200,20 @@ public List getFunctionsMetrics(String clientRole)
}
@Override
- public List getListOfConnectors(String clientRole) {
+ public List getListOfConnectors(AuthenticationParameters authParams) {
if (!isWorkerServiceAvailable()) {
throwUnavailableException();
}
-
- if (worker().getWorkerConfig().isAuthorizationEnabled() && !isSuperUser(clientRole)) {
- throw new RestException(Status.UNAUTHORIZED, "Client is not authorized to perform operation");
- }
-
+ throwIfNotSuperUser(authParams, "get list of connectors");
return this.worker().getConnectorsManager().getConnectorDefinitions();
}
@Override
- public void rebalance(final URI uri, final String clientRole) {
+ public void rebalance(final URI uri, final AuthenticationParameters authParams) {
if (!isWorkerServiceAvailable()) {
throwUnavailableException();
}
-
- if (worker().getWorkerConfig().isAuthorizationEnabled() && !isSuperUser(clientRole)) {
- log.error("Client [{}] is not authorized to rebalance cluster", clientRole);
- throw new RestException(Status.UNAUTHORIZED, "Client is not authorized to perform operation");
- }
+ throwIfNotSuperUser(authParams, "rebalance cluster");
if (worker().getLeaderService().isLeader()) {
try {
@@ -239,7 +235,8 @@ public void rebalance(final URI uri, final String clientRole) {
}
@Override
- public void drain(final URI uri, final String inWorkerId, final String clientRole, boolean calledOnLeaderUri) {
+ public void drain(final URI uri, final String inWorkerId, final AuthenticationParameters authParams,
+ boolean calledOnLeaderUri) {
if (!isWorkerServiceAvailable()) {
throwUnavailableException();
}
@@ -248,15 +245,13 @@ public void drain(final URI uri, final String inWorkerId, final String clientRol
final String workerId = (inWorkerId == null || inWorkerId.isEmpty()) ? actualWorkerId : inWorkerId;
if (log.isDebugEnabled()) {
- log.debug("drain called with URI={}, inWorkerId={}, workerId={}, clientRole={}, calledOnLeaderUri={}, "
- + "on actual worker-id={}",
- uri, inWorkerId, workerId, clientRole, calledOnLeaderUri, actualWorkerId);
+ log.debug("drain called with URI={}, inWorkerId={}, workerId={}, clientRole={}, originalPrincipal={}, "
+ + "calledOnLeaderUri={}, on actual worker-id={}",
+ uri, inWorkerId, workerId, authParams.getClientRole(), authParams.getOriginalPrincipal(),
+ calledOnLeaderUri, actualWorkerId);
}
- if (worker().getWorkerConfig().isAuthorizationEnabled() && !isSuperUser(clientRole)) {
- log.error("Client [{}] is not authorized to drain worker {}", clientRole, workerId);
- throw new RestException(Status.UNAUTHORIZED, "Client is not authorized to perform drain operation");
- }
+ throwIfNotSuperUser(authParams, "drain worker");
// Depending on which operations we decide to allow, we may add checks here to error/exception if
// calledOnLeaderUri is true on a non-leader
@@ -285,7 +280,8 @@ public void drain(final URI uri, final String inWorkerId, final String clientRol
}
@Override
- public LongRunningProcessStatus getDrainStatus(final URI uri, final String inWorkerId, final String clientRole,
+ public LongRunningProcessStatus getDrainStatus(final URI uri, final String inWorkerId,
+ final AuthenticationParameters authParams,
boolean calledOnLeaderUri) {
if (!isWorkerServiceAvailable()) {
throwUnavailableException();
@@ -296,15 +292,12 @@ public LongRunningProcessStatus getDrainStatus(final URI uri, final String inWor
if (log.isDebugEnabled()) {
log.debug("getDrainStatus called with uri={}, inWorkerId={}, workerId={}, clientRole={}, "
- + " calledOnLeaderUri={}, on actual workerId={}",
- uri, inWorkerId, workerId, clientRole, calledOnLeaderUri, actualWorkerId);
+ + "originalPrincipal={}, calledOnLeaderUri={}, on actual workerId={}",
+ uri, inWorkerId, workerId, authParams.getClientRole(), authParams.getOriginalPrincipal(),
+ calledOnLeaderUri, actualWorkerId);
}
- if (worker().getWorkerConfig().isAuthorizationEnabled() && !isSuperUser(clientRole)) {
- log.error("Client [{}] is not authorized to get drain status of worker {}", clientRole, workerId);
- throw new RestException(Status.UNAUTHORIZED,
- "Client is not authorized to get the status of a drain operation");
- }
+ throwIfNotSuperUser(authParams, "get drain status of worker");
// Depending on which operations we decide to allow, we may add checks here to error/exception if
// calledOnLeaderUri is true on a non-leader
@@ -321,7 +314,7 @@ public LongRunningProcessStatus getDrainStatus(final URI uri, final String inWor
}
@Override
- public Boolean isLeaderReady(final String clientRole) {
+ public boolean isLeaderReady(AuthenticationParameters authParams) {
if (!isWorkerServiceAvailable()) {
throwUnavailableException();
}
diff --git a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/v2/FunctionsApiV2Resource.java b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/v2/FunctionsApiV2Resource.java
index 9176013b783f6..0b125756b30a1 100644
--- a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/v2/FunctionsApiV2Resource.java
+++ b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/v2/FunctionsApiV2Resource.java
@@ -72,7 +72,7 @@ public Response registerFunction(final @PathParam("tenant") String tenant,
final @FormDataParam("functionDetails") String functionDetailsJson) {
return functions().registerFunction(tenant, namespace, functionName, uploadedInputStream, fileDetail,
- functionPkgUrl, functionDetailsJson, clientAppId());
+ functionPkgUrl, functionDetailsJson, authParams());
}
@PUT
@@ -93,7 +93,7 @@ public Response updateFunction(final @PathParam("tenant") String tenant,
final @FormDataParam("functionDetails") String functionDetailsJson) {
return functions().updateFunction(tenant, namespace, functionName, uploadedInputStream, fileDetail,
- functionPkgUrl, functionDetailsJson, clientAppId());
+ functionPkgUrl, functionDetailsJson, authParams());
}
@@ -110,7 +110,7 @@ public Response updateFunction(final @PathParam("tenant") String tenant,
public Response deregisterFunction(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace,
final @PathParam("functionName") String functionName) {
- return functions().deregisterFunction(tenant, namespace, functionName, clientAppId());
+ return functions().deregisterFunction(tenant, namespace, functionName, authParams());
}
@GET
@@ -129,8 +129,7 @@ public Response getFunctionInfo(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace,
final @PathParam("functionName") String functionName) throws IOException {
- return functions().getFunctionInfo(
- tenant, namespace, functionName, clientAppId());
+ return functions().getFunctionInfo(tenant, namespace, functionName, authParams());
}
@GET
@@ -151,7 +150,7 @@ public Response getFunctionInstanceStatus(final @PathParam("tenant") String tena
final @PathParam("instanceId") String instanceId) throws IOException {
return functions().getFunctionInstanceStatus(tenant, namespace, functionName, instanceId, uri.getRequestUri(),
- clientAppId());
+ authParams());
}
@GET
@@ -168,7 +167,7 @@ public Response getFunctionInstanceStatus(final @PathParam("tenant") String tena
public Response getFunctionStatus(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace,
final @PathParam("functionName") String functionName) throws IOException {
- return functions().getFunctionStatusV2(tenant, namespace, functionName, uri.getRequestUri(), clientAppId());
+ return functions().getFunctionStatusV2(tenant, namespace, functionName, uri.getRequestUri(), authParams());
}
@GET
@@ -184,7 +183,7 @@ public Response getFunctionStatus(final @PathParam("tenant") String tenant,
@Path("/{tenant}/{namespace}")
public Response listFunctions(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace) {
- return functions().listFunctions(tenant, namespace, clientAppId());
+ return functions().listFunctions(tenant, namespace, authParams());
}
@POST
@@ -207,7 +206,7 @@ public Response triggerFunction(final @PathParam("tenant") String tenant,
final @FormDataParam("dataStream") InputStream triggerStream,
final @FormDataParam("topic") String topic) {
return functions().triggerFunction(tenant, namespace, functionName, triggerValue, triggerStream, topic,
- clientAppId());
+ authParams());
}
@GET
@@ -226,7 +225,7 @@ public Response getFunctionState(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace,
final @PathParam("functionName") String functionName,
final @PathParam("key") String key) {
- return functions().getFunctionState(tenant, namespace, functionName, key, clientAppId());
+ return functions().getFunctionState(tenant, namespace, functionName, key, authParams());
}
@POST
@@ -243,7 +242,7 @@ public Response restartFunction(final @PathParam("tenant") String tenant,
final @PathParam("functionName") String functionName,
final @PathParam("instanceId") String instanceId) {
return functions().restartFunctionInstance(tenant, namespace, functionName, instanceId, uri.getRequestUri(),
- clientAppId());
+ authParams());
}
@POST
@@ -256,7 +255,7 @@ public Response restartFunction(final @PathParam("tenant") String tenant,
public Response restartFunction(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace,
final @PathParam("functionName") String functionName) {
- return functions().restartFunctionInstances(tenant, namespace, functionName, clientAppId());
+ return functions().restartFunctionInstances(tenant, namespace, functionName, authParams());
}
@POST
@@ -271,7 +270,7 @@ public Response stopFunction(final @PathParam("tenant") String tenant,
final @PathParam("functionName") String functionName,
final @PathParam("instanceId") String instanceId) {
return functions().stopFunctionInstance(tenant, namespace, functionName, instanceId, uri.getRequestUri(),
- clientAppId());
+ authParams());
}
@POST
@@ -284,7 +283,7 @@ public Response stopFunction(final @PathParam("tenant") String tenant,
public Response stopFunction(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace,
final @PathParam("functionName") String functionName) {
- return functions().stopFunctionInstances(tenant, namespace, functionName, clientAppId());
+ return functions().stopFunctionInstances(tenant, namespace, functionName, authParams());
}
@POST
@@ -296,7 +295,7 @@ public Response stopFunction(final @PathParam("tenant") String tenant,
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFunction(final @FormDataParam("data") InputStream uploadedInputStream,
final @FormDataParam("path") String path) {
- return functions().uploadFunction(uploadedInputStream, path, clientAppId());
+ return functions().uploadFunction(uploadedInputStream, path, authParams());
}
@GET
@@ -306,7 +305,7 @@ public Response uploadFunction(final @FormDataParam("data") InputStream uploaded
)
@Path("/download")
public Response downloadFunction(final @QueryParam("path") String path) {
- return functions().downloadFunction(path, clientAppId());
+ return functions().downloadFunction(path, authParams());
}
@GET
diff --git a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/v2/WorkerApiV2Resource.java b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/v2/WorkerApiV2Resource.java
index 496f6f43028fe..276d0ae86d876 100644
--- a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/v2/WorkerApiV2Resource.java
+++ b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/v2/WorkerApiV2Resource.java
@@ -39,11 +39,14 @@
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import lombok.extern.slf4j.Slf4j;
+import org.apache.pulsar.broker.authentication.AuthenticationDataSource;
+import org.apache.pulsar.broker.authentication.AuthenticationParameters;
import org.apache.pulsar.broker.web.AuthenticationFilter;
import org.apache.pulsar.client.admin.LongRunningProcessStatus;
import org.apache.pulsar.common.functions.WorkerInfo;
import org.apache.pulsar.common.io.ConnectorDefinition;
import org.apache.pulsar.functions.worker.WorkerService;
+import org.apache.pulsar.functions.worker.rest.FunctionApiResource;
import org.apache.pulsar.functions.worker.service.api.Workers;
@Slf4j
@@ -75,12 +78,25 @@ Workers extends WorkerService> workers() {
return get().getWorkers();
}
+ /**
+ * @deprecated use {@link #authParams()} instead
+ */
+ @Deprecated
public String clientAppId() {
return httpRequest != null
? (String) httpRequest.getAttribute(AuthenticationFilter.AuthenticatedRoleAttributeName)
: null;
}
+ public AuthenticationParameters authParams() {
+ return AuthenticationParameters.builder()
+ .clientRole(clientAppId())
+ .originalPrincipal(httpRequest.getHeader(FunctionApiResource.ORIGINAL_PRINCIPAL_HEADER))
+ .clientAuthenticationDataSource((AuthenticationDataSource)
+ httpRequest.getAttribute(AuthenticationFilter.AuthenticatedDataAttributeName))
+ .build();
+ }
+
@GET
@ApiOperation(
value = "Fetches information about the Pulsar cluster running Pulsar Functions",
@@ -94,7 +110,7 @@ public String clientAppId() {
@Path("/cluster")
@Produces(MediaType.APPLICATION_JSON)
public List getCluster() {
- return workers().getCluster(clientAppId());
+ return workers().getCluster(authParams());
}
@GET
@@ -109,7 +125,7 @@ public List getCluster() {
@Path("/cluster/leader")
@Produces(MediaType.APPLICATION_JSON)
public WorkerInfo getClusterLeader() {
- return workers().getClusterLeader(clientAppId());
+ return workers().getClusterLeader(authParams());
}
@GET
@@ -124,7 +140,7 @@ public WorkerInfo getClusterLeader() {
@Path("/assignments")
@Produces(MediaType.APPLICATION_JSON)
public Map> getAssignments() {
- return workers().getAssignments(clientAppId());
+ return workers().getAssignments(authParams());
}
@GET
@@ -139,7 +155,7 @@ public Map> getAssignments() {
})
@Path("/connectors")
public List getConnectorsList() throws IOException {
- return workers().getListOfConnectors(clientAppId());
+ return workers().getListOfConnectors(authParams());
}
@PUT
@@ -153,7 +169,7 @@ public List getConnectorsList() throws IOException {
})
@Path("/rebalance")
public void rebalance() {
- workers().rebalance(uri.getRequestUri(), clientAppId());
+ workers().rebalance(uri.getRequestUri(), authParams());
}
@PUT
@@ -169,7 +185,7 @@ public void rebalance() {
})
@Path("/leader/drain")
public void drainAtLeader(@QueryParam("workerId") String workerId) {
- workers().drain(uri.getRequestUri(), workerId, clientAppId(), true);
+ workers().drain(uri.getRequestUri(), workerId, authParams(), true);
}
@PUT
@@ -185,7 +201,7 @@ public void drainAtLeader(@QueryParam("workerId") String workerId) {
})
@Path("/drain")
public void drain() {
- workers().drain(uri.getRequestUri(), null, clientAppId(), false);
+ workers().drain(uri.getRequestUri(), null, authParams(), false);
}
@GET
@@ -199,7 +215,7 @@ public void drain() {
})
@Path("/leader/drain")
public LongRunningProcessStatus getDrainStatus(@QueryParam("workerId") String workerId) {
- return workers().getDrainStatus(uri.getRequestUri(), workerId, clientAppId(), true);
+ return workers().getDrainStatus(uri.getRequestUri(), workerId, authParams(), true);
}
@GET
@@ -213,7 +229,7 @@ public LongRunningProcessStatus getDrainStatus(@QueryParam("workerId") String wo
})
@Path("/drain")
public LongRunningProcessStatus getDrainStatus() {
- return workers().getDrainStatus(uri.getRequestUri(), null, clientAppId(), false);
+ return workers().getDrainStatus(uri.getRequestUri(), null, authParams(), false);
}
@GET
@@ -226,6 +242,6 @@ public LongRunningProcessStatus getDrainStatus() {
})
@Path("/cluster/leader/ready")
public Boolean isLeaderReady() {
- return workers().isLeaderReady(clientAppId());
+ return workers().isLeaderReady(authParams());
}
}
diff --git a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/v2/WorkerStatsApiV2Resource.java b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/v2/WorkerStatsApiV2Resource.java
index b6a7914f0fdfd..712505a4ba08a 100644
--- a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/v2/WorkerStatsApiV2Resource.java
+++ b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/v2/WorkerStatsApiV2Resource.java
@@ -34,9 +34,12 @@
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import lombok.extern.slf4j.Slf4j;
+import org.apache.pulsar.broker.authentication.AuthenticationDataSource;
+import org.apache.pulsar.broker.authentication.AuthenticationParameters;
import org.apache.pulsar.broker.web.AuthenticationFilter;
import org.apache.pulsar.common.policies.data.WorkerFunctionInstanceStats;
import org.apache.pulsar.functions.worker.WorkerService;
+import org.apache.pulsar.functions.worker.rest.FunctionApiResource;
import org.apache.pulsar.functions.worker.service.api.Workers;
@Slf4j
@@ -66,6 +69,19 @@ Workers extends WorkerService> workers() {
return get().getWorkers();
}
+ AuthenticationParameters authParams() {
+ return AuthenticationParameters.builder()
+ .clientRole(clientAppId())
+ .originalPrincipal(httpRequest.getHeader(FunctionApiResource.ORIGINAL_PRINCIPAL_HEADER))
+ .clientAuthenticationDataSource((AuthenticationDataSource)
+ httpRequest.getAttribute(AuthenticationFilter.AuthenticatedDataAttributeName))
+ .build();
+ }
+
+ /**
+ * @deprecated use {@link AuthenticationParameters} instead
+ */
+ @Deprecated
public String clientAppId() {
return httpRequest != null
? (String) httpRequest.getAttribute(AuthenticationFilter.AuthenticatedRoleAttributeName)
@@ -85,7 +101,7 @@ public String clientAppId() {
})
@Produces(MediaType.APPLICATION_JSON)
public List getMetrics() throws Exception {
- return workers().getWorkerMetrics(clientAppId());
+ return workers().getWorkerMetrics(authParams());
}
@GET
@@ -101,6 +117,6 @@ public List getMetrics() throws Exceptio
})
@Produces(MediaType.APPLICATION_JSON)
public List getStats() throws IOException {
- return workers().getFunctionsMetrics(clientAppId());
+ return workers().getFunctionsMetrics(authParams());
}
}
diff --git a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/v3/FunctionsApiV3Resource.java b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/v3/FunctionsApiV3Resource.java
index bca0cf4bf3d75..7bdc86d5fae3e 100644
--- a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/v3/FunctionsApiV3Resource.java
+++ b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/v3/FunctionsApiV3Resource.java
@@ -73,7 +73,7 @@ public void registerFunction(final @PathParam("tenant") String tenant,
final @FormDataParam("functionConfig") FunctionConfig functionConfig) {
functions().registerFunction(tenant, namespace, functionName, uploadedInputStream, fileDetail,
- functionPkgUrl, functionConfig, clientAppId(), clientAuthData());
+ functionPkgUrl, functionConfig, authParams());
}
@@ -90,7 +90,7 @@ public void updateFunction(final @PathParam("tenant") String tenant,
final @FormDataParam("updateOptions") UpdateOptionsImpl updateOptions) {
functions().updateFunction(tenant, namespace, functionName, uploadedInputStream, fileDetail,
- functionPkgUrl, functionConfig, clientAppId(), clientAuthData(), updateOptions);
+ functionPkgUrl, functionConfig, authParams(), updateOptions);
}
@@ -99,7 +99,7 @@ public void updateFunction(final @PathParam("tenant") String tenant,
public void deregisterFunction(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace,
final @PathParam("functionName") String functionName) {
- functions().deregisterFunction(tenant, namespace, functionName, clientAppId(), clientAuthData());
+ functions().deregisterFunction(tenant, namespace, functionName, authParams());
}
@GET
@@ -107,7 +107,7 @@ public void deregisterFunction(final @PathParam("tenant") String tenant,
public FunctionConfig getFunctionInfo(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace,
final @PathParam("functionName") String functionName) {
- return functions().getFunctionInfo(tenant, namespace, functionName, clientAppId(), clientAuthData());
+ return functions().getFunctionInfo(tenant, namespace, functionName, authParams());
}
@GET
@@ -115,7 +115,7 @@ public FunctionConfig getFunctionInfo(final @PathParam("tenant") String tenant,
@Path("/{tenant}/{namespace}")
public List listFunctions(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace) {
- return functions().listFunctions(tenant, namespace, clientAppId(), clientAuthData());
+ return functions().listFunctions(tenant, namespace, authParams());
}
@GET
@@ -137,7 +137,7 @@ public FunctionStatus.FunctionInstanceStatus.FunctionInstanceStatusData getFunct
final @PathParam("functionName") String functionName,
final @PathParam("instanceId") String instanceId) throws IOException {
return functions().getFunctionInstanceStatus(
- tenant, namespace, functionName, instanceId, uri.getRequestUri(), clientAppId(), clientAuthData());
+ tenant, namespace, functionName, instanceId, uri.getRequestUri(), authParams());
}
@GET
@@ -158,7 +158,7 @@ public FunctionStatus getFunctionStatus(
final @PathParam("namespace") String namespace,
final @PathParam("functionName") String functionName) throws IOException {
return functions().getFunctionStatus(
- tenant, namespace, functionName, uri.getRequestUri(), clientAppId(), clientAuthData());
+ tenant, namespace, functionName, uri.getRequestUri(), authParams());
}
@GET
@@ -178,7 +178,7 @@ public FunctionStatsImpl getFunctionStats(final @PathParam("tenant") String tena
final @PathParam("namespace") String namespace,
final @PathParam("functionName") String functionName) throws IOException {
return functions().getFunctionStats(tenant, namespace, functionName,
- uri.getRequestUri(), clientAppId(), clientAuthData());
+ uri.getRequestUri(), authParams());
}
@GET
@@ -200,7 +200,7 @@ public FunctionInstanceStatsDataImpl getFunctionInstanceStats(
final @PathParam("functionName") String functionName,
final @PathParam("instanceId") String instanceId) throws IOException {
return functions().getFunctionsInstanceStats(
- tenant, namespace, functionName, instanceId, uri.getRequestUri(), clientAppId(), clientAuthData());
+ tenant, namespace, functionName, instanceId, uri.getRequestUri(), authParams());
}
@POST
@@ -213,7 +213,7 @@ public String triggerFunction(final @PathParam("tenant") String tenant,
final @FormDataParam("dataStream") InputStream uploadedInputStream,
final @FormDataParam("topic") String topic) {
return functions().triggerFunction(tenant, namespace, functionName, input,
- uploadedInputStream, topic, clientAppId(), clientAuthData());
+ uploadedInputStream, topic, authParams());
}
@POST
@@ -231,7 +231,7 @@ public void restartFunction(final @PathParam("tenant") String tenant,
final @PathParam("functionName") String functionName,
final @PathParam("instanceId") String instanceId) {
functions().restartFunctionInstance(tenant, namespace, functionName, instanceId,
- this.uri.getRequestUri(), clientAppId(), clientAuthData());
+ this.uri.getRequestUri(), authParams());
}
@POST
@@ -246,7 +246,7 @@ public void restartFunction(final @PathParam("tenant") String tenant,
public void restartFunction(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace,
final @PathParam("functionName") String functionName) {
- functions().restartFunctionInstances(tenant, namespace, functionName, clientAppId(), clientAuthData());
+ functions().restartFunctionInstances(tenant, namespace, functionName, authParams());
}
@POST
@@ -263,7 +263,7 @@ public void stopFunction(final @PathParam("tenant") String tenant,
final @PathParam("functionName") String functionName,
final @PathParam("instanceId") String instanceId) {
functions().stopFunctionInstance(tenant, namespace, functionName, instanceId,
- this.uri.getRequestUri(), clientAppId(), clientAuthData());
+ this.uri.getRequestUri(), authParams());
}
@POST
@@ -278,7 +278,7 @@ public void stopFunction(final @PathParam("tenant") String tenant,
public void stopFunction(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace,
final @PathParam("functionName") String functionName) {
- functions().stopFunctionInstances(tenant, namespace, functionName, clientAppId(), clientAuthData());
+ functions().stopFunctionInstances(tenant, namespace, functionName, authParams());
}
@POST
@@ -295,7 +295,7 @@ public void startFunction(final @PathParam("tenant") String tenant,
final @PathParam("functionName") String functionName,
final @PathParam("instanceId") String instanceId) {
functions().startFunctionInstance(tenant, namespace, functionName, instanceId,
- this.uri.getRequestUri(), clientAppId(), clientAuthData());
+ this.uri.getRequestUri(), authParams());
}
@POST
@@ -310,7 +310,7 @@ public void startFunction(final @PathParam("tenant") String tenant,
public void startFunction(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace,
final @PathParam("functionName") String functionName) {
- functions().startFunctionInstances(tenant, namespace, functionName, clientAppId(), clientAuthData());
+ functions().startFunctionInstances(tenant, namespace, functionName, authParams());
}
@POST
@@ -318,13 +318,13 @@ public void startFunction(final @PathParam("tenant") String tenant,
@Consumes(MediaType.MULTIPART_FORM_DATA)
public void uploadFunction(final @FormDataParam("data") InputStream uploadedInputStream,
final @FormDataParam("path") String path) {
- functions().uploadFunction(uploadedInputStream, path, clientAppId(), clientAuthData());
+ functions().uploadFunction(uploadedInputStream, path, authParams());
}
@GET
@Path("/download")
public StreamingOutput downloadFunction(final @QueryParam("path") String path) {
- return functions().downloadFunction(path, clientAppId(), clientAuthData());
+ return functions().downloadFunction(path, authParams());
}
@GET
@@ -344,7 +344,7 @@ public StreamingOutput downloadFunction(
final @QueryParam("transform-function") boolean transformFunction) {
return functions()
- .downloadFunction(tenant, namespace, functionName, clientAppId(), clientAuthData(), transformFunction);
+ .downloadFunction(tenant, namespace, functionName, authParams(), transformFunction);
}
@GET
@@ -368,7 +368,7 @@ public List getConnectorsList() throws IOException {
})
@Path("/builtins/reload")
public void reloadBuiltinFunctions() throws IOException {
- functions().reloadBuiltinFunctions(clientAppId(), clientAuthData());
+ functions().reloadBuiltinFunctions(authParams());
}
@GET
@@ -385,7 +385,7 @@ public void reloadBuiltinFunctions() throws IOException {
@Path("/builtins")
@Produces(MediaType.APPLICATION_JSON)
public List getBuiltinFunctions() {
- return functions().getBuiltinFunctions(clientAppId(), clientAuthData());
+ return functions().getBuiltinFunctions(authParams());
}
@GET
@@ -394,7 +394,7 @@ public FunctionState getFunctionState(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace,
final @PathParam("functionName") String functionName,
final @PathParam("key") String key) throws IOException {
- return functions().getFunctionState(tenant, namespace, functionName, key, clientAppId(), clientAuthData());
+ return functions().getFunctionState(tenant, namespace, functionName, key, authParams());
}
@POST
@@ -405,7 +405,7 @@ public void putFunctionState(final @PathParam("tenant") String tenant,
final @PathParam("functionName") String functionName,
final @PathParam("key") String key,
final @FormDataParam("state") FunctionState stateJson) throws IOException {
- functions().putFunctionState(tenant, namespace, functionName, key, stateJson, clientAppId(), clientAuthData());
+ functions().putFunctionState(tenant, namespace, functionName, key, stateJson, authParams());
}
@PUT
@@ -427,6 +427,6 @@ public void updateFunctionOnWorkerLeader(final @PathParam("tenant") String tenan
final @FormDataParam("delete") boolean delete) {
functions().updateFunctionOnWorkerLeader(tenant, namespace, functionName, uploadedInputStream,
- delete, uri.getRequestUri(), clientAppId(), clientAuthData());
+ delete, uri.getRequestUri(), authParams());
}
}
diff --git a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/v3/SinksApiV3Resource.java b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/v3/SinksApiV3Resource.java
index b110c8f72c677..8081f76cfd8ec 100644
--- a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/v3/SinksApiV3Resource.java
+++ b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/v3/SinksApiV3Resource.java
@@ -70,7 +70,7 @@ public void registerSink(final @PathParam("tenant") String tenant,
final @FormDataParam("sinkConfig") SinkConfig sinkConfig) {
sinks().registerSink(tenant, namespace, sinkName, uploadedInputStream, fileDetail,
- functionPkgUrl, sinkConfig, clientAppId(), clientAuthData());
+ functionPkgUrl, sinkConfig, authParams());
}
@PUT
@@ -86,7 +86,7 @@ public void updateSink(final @PathParam("tenant") String tenant,
final @FormDataParam("updateOptions") UpdateOptionsImpl updateOptions) {
sinks().updateSink(tenant, namespace, sinkName, uploadedInputStream, fileDetail,
- functionPkgUrl, sinkConfig, clientAppId(), clientAuthData(), updateOptions);
+ functionPkgUrl, sinkConfig, authParams(), updateOptions);
}
@DELETE
@@ -94,7 +94,7 @@ public void updateSink(final @PathParam("tenant") String tenant,
public void deregisterSink(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace,
final @PathParam("sinkName") String sinkName) {
- sinks().deregisterFunction(tenant, namespace, sinkName, clientAppId(), clientAuthData());
+ sinks().deregisterFunction(tenant, namespace, sinkName, authParams());
}
@GET
@@ -103,7 +103,7 @@ public SinkConfig getSinkInfo(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace,
final @PathParam("sinkName") String sinkName)
throws IOException {
- return sinks().getSinkInfo(tenant, namespace, sinkName);
+ return sinks().getSinkInfo(tenant, namespace, sinkName, authParams());
}
@GET
@@ -124,9 +124,8 @@ public SinkStatus.SinkInstanceStatus.SinkInstanceStatusData getSinkInstanceStatu
final @PathParam("namespace") String namespace,
final @PathParam("sinkName") String sinkName,
final @PathParam("instanceId") String instanceId) throws IOException {
- return sinks()
- .getSinkInstanceStatus(tenant, namespace, sinkName, instanceId, uri.getRequestUri(), clientAppId(),
- clientAuthData());
+ return sinks().getSinkInstanceStatus(tenant, namespace, sinkName, instanceId, uri.getRequestUri(),
+ authParams());
}
@GET
@@ -145,14 +144,14 @@ public SinkStatus.SinkInstanceStatus.SinkInstanceStatusData getSinkInstanceStatu
public SinkStatus getSinkStatus(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace,
final @PathParam("sinkName") String sinkName) throws IOException {
- return sinks().getSinkStatus(tenant, namespace, sinkName, uri.getRequestUri(), clientAppId(), clientAuthData());
+ return sinks().getSinkStatus(tenant, namespace, sinkName, uri.getRequestUri(), authParams());
}
@GET
@Path("/{tenant}/{namespace}")
public List listSink(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace) {
- return sinks().listFunctions(tenant, namespace, clientAppId(), clientAuthData());
+ return sinks().listFunctions(tenant, namespace, authParams());
}
@POST
@@ -169,7 +168,7 @@ public void restartSink(final @PathParam("tenant") String tenant,
final @PathParam("sinkName") String sinkName,
final @PathParam("instanceId") String instanceId) {
sinks().restartFunctionInstance(tenant, namespace, sinkName, instanceId, this.uri.getRequestUri(),
- clientAppId(), clientAuthData());
+ authParams());
}
@POST
@@ -182,7 +181,7 @@ public void restartSink(final @PathParam("tenant") String tenant,
public void restartSink(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace,
final @PathParam("sinkName") String sinkName) {
- sinks().restartFunctionInstances(tenant, namespace, sinkName, clientAppId(), clientAuthData());
+ sinks().restartFunctionInstances(tenant, namespace, sinkName, authParams());
}
@POST
@@ -196,8 +195,8 @@ public void stopSink(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace,
final @PathParam("sinkName") String sinkName,
final @PathParam("instanceId") String instanceId) {
- sinks().stopFunctionInstance(tenant, namespace, sinkName, instanceId, this.uri.getRequestUri(), clientAppId(),
- clientAuthData());
+ sinks().stopFunctionInstance(tenant, namespace, sinkName, instanceId, this.uri.getRequestUri(),
+ authParams());
}
@POST
@@ -210,7 +209,7 @@ public void stopSink(final @PathParam("tenant") String tenant,
public void stopSink(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace,
final @PathParam("sinkName") String sinkName) {
- sinks().stopFunctionInstances(tenant, namespace, sinkName, clientAppId(), clientAuthData());
+ sinks().stopFunctionInstances(tenant, namespace, sinkName, authParams());
}
@POST
@@ -224,8 +223,8 @@ public void startSink(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace,
final @PathParam("sinkName") String sinkName,
final @PathParam("instanceId") String instanceId) {
- sinks().startFunctionInstance(tenant, namespace, sinkName, instanceId, this.uri.getRequestUri(), clientAppId(),
- clientAuthData());
+ sinks().startFunctionInstance(tenant, namespace, sinkName, instanceId, this.uri.getRequestUri(),
+ authParams());
}
@POST
@@ -238,7 +237,7 @@ public void startSink(final @PathParam("tenant") String tenant,
public void startSink(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace,
final @PathParam("sinkName") String sinkName) {
- sinks().startFunctionInstances(tenant, namespace, sinkName, clientAppId(), clientAuthData());
+ sinks().startFunctionInstances(tenant, namespace, sinkName, authParams());
}
@GET
@@ -278,6 +277,6 @@ public List getSinkConfigDefinition(
})
@Path("/reloadBuiltInSinks")
public void reloadSinks() {
- sinks().reloadConnectors(clientAppId(), clientAuthData());
+ sinks().reloadConnectors(authParams());
}
}
diff --git a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/v3/SourcesApiV3Resource.java b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/v3/SourcesApiV3Resource.java
index a669d4f089dd0..23df423045090 100644
--- a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/v3/SourcesApiV3Resource.java
+++ b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/v3/SourcesApiV3Resource.java
@@ -70,7 +70,7 @@ public void registerSource(final @PathParam("tenant") String tenant,
final @FormDataParam("sourceConfig") SourceConfig sourceConfig) {
sources().registerSource(tenant, namespace, sourceName, uploadedInputStream, fileDetail,
- functionPkgUrl, sourceConfig, clientAppId(), clientAuthData());
+ functionPkgUrl, sourceConfig, authParams());
}
@@ -87,7 +87,7 @@ public void updateSource(final @PathParam("tenant") String tenant,
final @FormDataParam("updateOptions") UpdateOptionsImpl updateOptions) {
sources().updateSource(tenant, namespace, sourceName, uploadedInputStream, fileDetail,
- functionPkgUrl, sourceConfig, clientAppId(), clientAuthData(), updateOptions);
+ functionPkgUrl, sourceConfig, authParams(), updateOptions);
}
@@ -96,7 +96,7 @@ public void updateSource(final @PathParam("tenant") String tenant,
public void deregisterSource(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace,
final @PathParam("sourceName") String sourceName) {
- sources().deregisterFunction(tenant, namespace, sourceName, clientAppId(), clientAuthData());
+ sources().deregisterFunction(tenant, namespace, sourceName, authParams());
}
@GET
@@ -106,7 +106,7 @@ public SourceConfig getSourceInfo(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace,
final @PathParam("sourceName") String sourceName)
throws IOException {
- return sources().getSourceInfo(tenant, namespace, sourceName);
+ return sources().getSourceInfo(tenant, namespace, sourceName, authParams());
}
@GET
@@ -127,8 +127,8 @@ public SourceStatus.SourceInstanceStatus.SourceInstanceStatusData getSourceInsta
final @PathParam("namespace") String namespace,
final @PathParam("sourceName") String sourceName,
final @PathParam("instanceId") String instanceId) throws IOException {
- return sources().getSourceInstanceStatus(
- tenant, namespace, sourceName, instanceId, uri.getRequestUri(), clientAppId(), clientAuthData());
+ return sources().getSourceInstanceStatus(tenant, namespace, sourceName, instanceId, uri.getRequestUri(),
+ authParams());
}
@GET
@@ -148,7 +148,7 @@ public SourceStatus getSourceStatus(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace,
final @PathParam("sourceName") String sourceName) throws IOException {
return sources()
- .getSourceStatus(tenant, namespace, sourceName, uri.getRequestUri(), clientAppId(), clientAuthData());
+ .getSourceStatus(tenant, namespace, sourceName, uri.getRequestUri(), authParams());
}
@GET
@@ -156,7 +156,7 @@ public SourceStatus getSourceStatus(final @PathParam("tenant") String tenant,
@Path("/{tenant}/{namespace}")
public List listSources(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace) {
- return sources().listFunctions(tenant, namespace, clientAppId(), clientAuthData());
+ return sources().listFunctions(tenant, namespace, authParams());
}
@POST
@@ -173,7 +173,7 @@ public void restartSource(final @PathParam("tenant") String tenant,
final @PathParam("sourceName") String sourceName,
final @PathParam("instanceId") String instanceId) {
sources().restartFunctionInstance(tenant, namespace, sourceName, instanceId, this.uri.getRequestUri(),
- clientAppId(), clientAuthData());
+ authParams());
}
@POST
@@ -186,7 +186,7 @@ public void restartSource(final @PathParam("tenant") String tenant,
public void restartSource(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace,
final @PathParam("sourceName") String sourceName) {
- sources().restartFunctionInstances(tenant, namespace, sourceName, clientAppId(), clientAuthData());
+ sources().restartFunctionInstances(tenant, namespace, sourceName, authParams());
}
@POST
@@ -201,7 +201,7 @@ public void stopSource(final @PathParam("tenant") String tenant,
final @PathParam("sourceName") String sourceName,
final @PathParam("instanceId") String instanceId) {
sources().stopFunctionInstance(tenant, namespace, sourceName, instanceId, this.uri.getRequestUri(),
- clientAppId(), clientAuthData());
+ authParams());
}
@POST
@@ -214,7 +214,7 @@ public void stopSource(final @PathParam("tenant") String tenant,
public void stopSource(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace,
final @PathParam("sourceName") String sourceName) {
- sources().stopFunctionInstances(tenant, namespace, sourceName, clientAppId(), clientAuthData());
+ sources().stopFunctionInstances(tenant, namespace, sourceName, authParams());
}
@POST
@@ -229,7 +229,7 @@ public void startSource(final @PathParam("tenant") String tenant,
final @PathParam("sourceName") String sourceName,
final @PathParam("instanceId") String instanceId) {
sources().startFunctionInstance(tenant, namespace, sourceName, instanceId, this.uri.getRequestUri(),
- clientAppId(), clientAuthData());
+ authParams());
}
@POST
@@ -242,7 +242,7 @@ public void startSource(final @PathParam("tenant") String tenant,
public void startSource(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace,
final @PathParam("sourceName") String sourceName) {
- sources().startFunctionInstances(tenant, namespace, sourceName, clientAppId(), clientAuthData());
+ sources().startFunctionInstances(tenant, namespace, sourceName, authParams());
}
@GET
@@ -293,6 +293,6 @@ public List getSourceConfigDefinition(
})
@Path("/reloadBuiltInSources")
public void reloadSources() {
- sources().reloadConnectors(clientAppId(), clientAuthData());
+ sources().reloadConnectors(authParams());
}
}
diff --git a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/service/api/Component.java b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/service/api/Component.java
index fc01ec55b6c4c..770cced1731da 100644
--- a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/service/api/Component.java
+++ b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/service/api/Component.java
@@ -22,8 +22,7 @@
import java.net.URI;
import java.util.List;
import javax.ws.rs.core.StreamingOutput;
-import org.apache.pulsar.broker.authentication.AuthenticationDataHttps;
-import org.apache.pulsar.broker.authentication.AuthenticationDataSource;
+import org.apache.pulsar.broker.authentication.AuthenticationParameters;
import org.apache.pulsar.common.functions.FunctionConfig;
import org.apache.pulsar.common.functions.FunctionState;
import org.apache.pulsar.common.io.ConnectorDefinition;
@@ -40,167 +39,55 @@ public interface Component {
W worker();
- void deregisterFunction(String tenant,
- String namespace,
- String componentName,
- String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps);
-
- @Deprecated
- default void deregisterFunction(String tenant,
- String namespace,
- String componentName,
- String clientRole,
- AuthenticationDataHttps clientAuthenticationDataHttps) {
- deregisterFunction(
- tenant,
- namespace,
- componentName,
- clientRole,
- (AuthenticationDataSource) clientAuthenticationDataHttps);
- }
-
- FunctionConfig getFunctionInfo(String tenant,
- String namespace,
- String componentName,
- String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps);
-
- void stopFunctionInstance(String tenant,
- String namespace,
- String componentName,
- String instanceId,
- URI uri,
- String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps);
-
- void startFunctionInstance(String tenant,
- String namespace,
- String componentName,
- String instanceId,
- URI uri,
- String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps);
-
- void restartFunctionInstance(String tenant,
- String namespace,
- String componentName,
- String instanceId,
- URI uri,
- String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps);
-
- void startFunctionInstances(String tenant,
- String namespace,
- String componentName,
- String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps);
-
- void stopFunctionInstances(String tenant,
- String namespace,
- String componentName,
- String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps);
-
- void restartFunctionInstances(String tenant,
- String namespace,
- String componentName,
- String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps);
-
- FunctionStatsImpl getFunctionStats(String tenant,
- String namespace,
- String componentName,
- URI uri,
- String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps);
-
- FunctionInstanceStatsDataImpl getFunctionsInstanceStats(String tenant,
- String namespace,
- String componentName,
- String instanceId,
- URI uri,
- String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps);
-
- String triggerFunction(String tenant,
- String namespace,
- String functionName,
- String input,
- InputStream uploadedInputStream,
- String topic,
- String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps);
-
- List listFunctions(String tenant,
- String namespace,
- String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps);
-
- FunctionState getFunctionState(String tenant,
- String namespace,
- String functionName,
- String key,
- String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps);
-
- void putFunctionState(String tenant,
- String namespace,
- String functionName,
- String key,
- FunctionState state,
- String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps);
-
- void uploadFunction(InputStream uploadedInputStream,
- String path,
- String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps);
-
- StreamingOutput downloadFunction(String path,
- String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps);
-
- @Deprecated
- default StreamingOutput downloadFunction(String path,
- String clientRole,
- AuthenticationDataHttps clientAuthenticationDataHttps) {
- return downloadFunction(path, clientRole, (AuthenticationDataSource) clientAuthenticationDataHttps);
- }
-
- StreamingOutput downloadFunction(String tenant,
- String namespace,
- String componentName,
- String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps,
- boolean transformFunction);
-
- @Deprecated
- default StreamingOutput downloadFunction(String tenant,
- String namespace,
- String componentName,
- String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps) {
- return downloadFunction(tenant, namespace, componentName, clientRole, clientAuthenticationDataHttps, false);
- }
-
- @Deprecated
- default StreamingOutput downloadFunction(String tenant,
- String namespace,
- String componentName,
- String clientRole,
- AuthenticationDataHttps clientAuthenticationDataHttps) {
- return downloadFunction(
- tenant,
- namespace,
- componentName,
- clientRole,
- (AuthenticationDataSource) clientAuthenticationDataHttps,
- false);
- }
+ void deregisterFunction(String tenant, String namespace, String componentName, AuthenticationParameters authParams);
- List getListOfConnectors();
+ FunctionConfig getFunctionInfo(String tenant, String namespace, String componentName,
+ AuthenticationParameters authParams);
+
+ void stopFunctionInstance(String tenant, String namespace, String componentName, String instanceId, URI uri,
+ AuthenticationParameters authParams);
+
+ void startFunctionInstance(String tenant, String namespace, String componentName, String instanceId, URI uri,
+ AuthenticationParameters authParams);
+
+ void restartFunctionInstance(String tenant, String namespace, String componentName, String instanceId, URI uri,
+ AuthenticationParameters authParams);
+
+ void startFunctionInstances(String tenant, String namespace, String componentName,
+ AuthenticationParameters authParams);
+
+ void stopFunctionInstances(String tenant, String namespace, String componentName,
+ AuthenticationParameters authParams);
+
+ void restartFunctionInstances(String tenant, String namespace, String componentName,
+ AuthenticationParameters authParams);
+
+ FunctionStatsImpl getFunctionStats(String tenant, String namespace, String componentName, URI uri,
+ AuthenticationParameters authParams);
+
+ FunctionInstanceStatsDataImpl getFunctionsInstanceStats(String tenant, String namespace, String componentName,
+ String instanceId, URI uri,
+ AuthenticationParameters authParams);
+ String triggerFunction(String tenant, String namespace, String functionName, String input,
+ InputStream uploadedInputStream, String topic, AuthenticationParameters authParams);
+
+ List listFunctions(String tenant, String namespace, AuthenticationParameters authParams);
+
+ FunctionState getFunctionState(String tenant, String namespace, String functionName, String key,
+ AuthenticationParameters authParams);
+
+ void putFunctionState(String tenant, String namespace, String functionName, String key, FunctionState state,
+ AuthenticationParameters authParams);
+
+ void uploadFunction(InputStream uploadedInputStream, String path, AuthenticationParameters authParams);
+
+ StreamingOutput downloadFunction(String path, AuthenticationParameters authParams);
+
+ StreamingOutput downloadFunction(String tenant, String namespace, String componentName,
+ AuthenticationParameters authParams, boolean transformFunction);
+
+ List getListOfConnectors();
- void reloadConnectors(String clientRole, AuthenticationDataSource clientAuthenticationDataHttps);
+ void reloadConnectors(AuthenticationParameters authParams);
}
diff --git a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/service/api/Functions.java b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/service/api/Functions.java
index 954ab1d26182f..28bc73fd0a831 100644
--- a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/service/api/Functions.java
+++ b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/service/api/Functions.java
@@ -22,8 +22,7 @@
import java.io.InputStream;
import java.net.URI;
import java.util.List;
-import org.apache.pulsar.broker.authentication.AuthenticationDataHttps;
-import org.apache.pulsar.broker.authentication.AuthenticationDataSource;
+import org.apache.pulsar.broker.authentication.AuthenticationParameters;
import org.apache.pulsar.common.functions.FunctionConfig;
import org.apache.pulsar.common.functions.FunctionDefinition;
import org.apache.pulsar.common.functions.UpdateOptionsImpl;
@@ -46,8 +45,7 @@ public interface Functions extends Component {
* @param fileDetail A form-data content disposition header
* @param functionPkgUrl URL path of the Pulsar Function package
* @param functionConfig Configuration of Pulsar Function
- * @param clientRole Client role for running the pulsar function
- * @param clientAuthenticationDataHttps Authentication status of the http client
+ * @param authParams the authentication parameters associated with the request
*/
void registerFunction(String tenant,
String namespace,
@@ -56,35 +54,7 @@ void registerFunction(String tenant,
FormDataContentDisposition fileDetail,
String functionPkgUrl,
FunctionConfig functionConfig,
- String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps);
-
- /**
- * This method uses an incorrect signature 'AuthenticationDataHttps' that prevents the extension of auth status,
- * so it is marked as deprecated and kept here only for backward compatibility. Please use the method that accepts
- * the signature of the AuthenticationDataSource.
- */
- @Deprecated
- default void registerFunction(String tenant,
- String namespace,
- String functionName,
- InputStream uploadedInputStream,
- FormDataContentDisposition fileDetail,
- String functionPkgUrl,
- FunctionConfig functionConfig,
- String clientRole,
- AuthenticationDataHttps clientAuthenticationDataHttps) {
- registerFunction(
- tenant,
- namespace,
- functionName,
- uploadedInputStream,
- fileDetail,
- functionPkgUrl,
- functionConfig,
- clientRole,
- (AuthenticationDataSource) clientAuthenticationDataHttps);
- }
+ AuthenticationParameters authParams);
/**
* Update a function.
@@ -95,8 +65,7 @@ default void registerFunction(String tenant,
* @param fileDetail A form-data content disposition header
* @param functionPkgUrl URL path of the Pulsar Function package
* @param functionConfig Configuration of Pulsar Function
- * @param clientRole Client role for running the Pulsar Function
- * @param clientAuthenticationDataHttps Authentication status of the http client
+ * @param authParams the authentication parameters associated with the request
* @param updateOptions Options while updating the function
*/
void updateFunction(String tenant,
@@ -106,66 +75,31 @@ void updateFunction(String tenant,
FormDataContentDisposition fileDetail,
String functionPkgUrl,
FunctionConfig functionConfig,
- String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps,
+ AuthenticationParameters authParams,
UpdateOptionsImpl updateOptions);
- /**
- * This method uses an incorrect signature 'AuthenticationDataHttps' that prevents the extension of auth status,
- * so it is marked as deprecated and kept here only for backward compatibility. Please use the method that accepts
- * the signature of the AuthenticationDataSource.
- */
- @Deprecated
- default void updateFunction(String tenant,
- String namespace,
- String functionName,
- InputStream uploadedInputStream,
- FormDataContentDisposition fileDetail,
- String functionPkgUrl,
- FunctionConfig functionConfig,
- String clientRole,
- AuthenticationDataHttps clientAuthenticationDataHttps,
- UpdateOptionsImpl updateOptions) {
- updateFunction(
- tenant,
- namespace,
- functionName,
- uploadedInputStream,
- fileDetail,
- functionPkgUrl,
- functionConfig,
- clientRole,
- (AuthenticationDataSource) clientAuthenticationDataHttps,
- updateOptions);
- }
-
void updateFunctionOnWorkerLeader(String tenant,
String namespace,
String functionName,
InputStream uploadedInputStream,
boolean delete,
URI uri,
- String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps);
+ AuthenticationParameters authParams);
FunctionStatus getFunctionStatus(String tenant,
String namespace,
String componentName,
URI uri,
- String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps);
+ AuthenticationParameters authParams);
FunctionInstanceStatusData getFunctionInstanceStatus(String tenant,
String namespace,
String componentName,
String instanceId,
URI uri,
- String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps);
+ AuthenticationParameters authParams);
- void reloadBuiltinFunctions(String clientRole, AuthenticationDataSource clientAuthenticationDataHttps)
- throws IOException;
+ void reloadBuiltinFunctions(AuthenticationParameters authParams) throws IOException;
- List getBuiltinFunctions(String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps);
+ List getBuiltinFunctions(AuthenticationParameters authParams);
}
diff --git a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/service/api/FunctionsV2.java b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/service/api/FunctionsV2.java
index 6a4be7cdf6f0e..d78d241b3e6a0 100644
--- a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/service/api/FunctionsV2.java
+++ b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/service/api/FunctionsV2.java
@@ -23,6 +23,7 @@
import java.net.URI;
import java.util.List;
import javax.ws.rs.core.Response;
+import org.apache.pulsar.broker.authentication.AuthenticationParameters;
import org.apache.pulsar.common.io.ConnectorDefinition;
import org.apache.pulsar.functions.worker.WorkerService;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
@@ -35,20 +36,20 @@ public interface FunctionsV2 {
Response getFunctionInfo(String tenant,
String namespace,
String functionName,
- String clientRole) throws IOException;
+ AuthenticationParameters authParams) throws IOException;
Response getFunctionInstanceStatus(String tenant,
- String namespace,
- String functionName,
- String instanceId,
- URI uri,
- String clientRole) throws IOException;
+ String namespace,
+ String functionName,
+ String instanceId,
+ URI uri,
+ AuthenticationParameters authParams) throws IOException;
Response getFunctionStatusV2(String tenant,
String namespace,
String functionName,
URI requestUri,
- String clientRole) throws IOException;
+ AuthenticationParameters authParams) throws IOException;
Response registerFunction(String tenant,
String namespace,
@@ -57,7 +58,8 @@ Response registerFunction(String tenant,
FormDataContentDisposition fileDetail,
String functionPkgUrl,
String functionDetailsJson,
- String clientRole);
+ AuthenticationParameters authParams);
+
Response updateFunction(String tenant,
String namespace,
@@ -66,14 +68,12 @@ Response updateFunction(String tenant,
FormDataContentDisposition fileDetail,
String functionPkgUrl,
String functionDetailsJson,
- String clientRole);
+ AuthenticationParameters authParams);
- Response deregisterFunction(String tenant,
- String namespace,
- String functionName,
- String clientAppId);
+ Response deregisterFunction(String tenant, String namespace, String functionName,
+ AuthenticationParameters authParams);
- Response listFunctions(String tenant, String namespace, String clientRole);
+ Response listFunctions(String tenant, String namespace, AuthenticationParameters authParams);
Response triggerFunction(String tenant,
String namespace,
@@ -81,45 +81,44 @@ Response triggerFunction(String tenant,
String triggerValue,
InputStream triggerStream,
String topic,
- String clientRole);
+ AuthenticationParameters authParams);
Response getFunctionState(String tenant,
String namespace,
String functionName,
String key,
- String clientRole);
-
+ AuthenticationParameters authParams);
Response restartFunctionInstance(String tenant,
String namespace,
String functionName,
String instanceId,
URI uri,
- String clientRole);
+ AuthenticationParameters authParams);
+
Response restartFunctionInstances(String tenant,
String namespace,
String functionName,
- String clientRole);
+ AuthenticationParameters authParams);
Response stopFunctionInstance(String tenant,
String namespace,
String functionName,
String instanceId,
URI uri,
- String clientRole);
+ AuthenticationParameters authParams);
Response stopFunctionInstances(String tenant,
String namespace,
String functionName,
- String clientRole);
+ AuthenticationParameters authParams);
Response uploadFunction(InputStream uploadedInputStream,
String path,
- String clientRole);
-
- Response downloadFunction(String path, String clientRole);
+ AuthenticationParameters authParams);
+ Response downloadFunction(String path, AuthenticationParameters authParams);
List getListOfConnectors();
diff --git a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/service/api/Sinks.java b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/service/api/Sinks.java
index 2c0dcb82e0dbc..c977f55df4bf3 100644
--- a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/service/api/Sinks.java
+++ b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/service/api/Sinks.java
@@ -21,8 +21,7 @@
import java.io.InputStream;
import java.net.URI;
import java.util.List;
-import org.apache.pulsar.broker.authentication.AuthenticationDataHttps;
-import org.apache.pulsar.broker.authentication.AuthenticationDataSource;
+import org.apache.pulsar.broker.authentication.AuthenticationParameters;
import org.apache.pulsar.common.functions.UpdateOptionsImpl;
import org.apache.pulsar.common.io.ConfigFieldDefinition;
import org.apache.pulsar.common.io.ConnectorDefinition;
@@ -46,8 +45,7 @@ public interface Sinks extends Component {
* @param fileDetail A form-data content disposition header
* @param sinkPkgUrl URL path of the Pulsar Sink package
* @param sinkConfig Configuration of Pulsar Sink
- * @param clientRole Client role for running the Pulsar Sink
- * @param clientAuthenticationDataHttps Authentication status of the http client
+ * @param authParams the authentication parameters associated with the request
*/
void registerSink(String tenant,
String namespace,
@@ -56,35 +54,7 @@ void registerSink(String tenant,
FormDataContentDisposition fileDetail,
String sinkPkgUrl,
SinkConfig sinkConfig,
- String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps);
-
- /**
- * This method uses an incorrect signature 'AuthenticationDataHttps' that prevents the extension of auth status,
- * so it is marked as deprecated and kept here only for backward compatibility. Please use the method that accepts
- * the signature of the AuthenticationDataSource.
- */
- @Deprecated
- default void registerSink(String tenant,
- String namespace,
- String sinkName,
- InputStream uploadedInputStream,
- FormDataContentDisposition fileDetail,
- String sinkPkgUrl,
- SinkConfig sinkConfig,
- String clientRole,
- AuthenticationDataHttps clientAuthenticationDataHttps) {
- registerSink(
- tenant,
- namespace,
- sinkName,
- uploadedInputStream,
- fileDetail,
- sinkPkgUrl,
- sinkConfig,
- clientRole,
- (AuthenticationDataSource) clientAuthenticationDataHttps);
- }
+ AuthenticationParameters authParams);
/**
* Update a function.
@@ -95,8 +65,7 @@ default void registerSink(String tenant,
* @param fileDetail A form-data content disposition header
* @param sinkPkgUrl URL path of the Pulsar Sink package
* @param sinkConfig Configuration of Pulsar Sink
- * @param clientRole Client role for running the Pulsar Sink
- * @param clientAuthenticationDataHttps Authentication status of the http client
+ * @param authParams the authentication parameters associated with the request
* @param updateOptions Options while updating the sink
*/
void updateSink(String tenant,
@@ -106,57 +75,26 @@ void updateSink(String tenant,
FormDataContentDisposition fileDetail,
String sinkPkgUrl,
SinkConfig sinkConfig,
- String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps,
+ AuthenticationParameters authParams,
UpdateOptionsImpl updateOptions);
- /**
- * This method uses an incorrect signature 'AuthenticationDataHttps' that prevents the extension of auth status,
- * so it is marked as deprecated and kept here only for backward compatibility. Please use the method that accepts
- * the signature of the AuthenticationDataSource.
- */
- @Deprecated
- default void updateSink(String tenant,
- String namespace,
- String sinkName,
- InputStream uploadedInputStream,
- FormDataContentDisposition fileDetail,
- String sinkPkgUrl,
- SinkConfig sinkConfig,
- String clientRole,
- AuthenticationDataHttps clientAuthenticationDataHttps,
- UpdateOptionsImpl updateOptions) {
- updateSink(
- tenant,
- namespace,
- sinkName,
- uploadedInputStream,
- fileDetail,
- sinkPkgUrl,
- sinkConfig,
- clientRole,
- (AuthenticationDataSource) clientAuthenticationDataHttps,
- updateOptions);
- }
-
SinkInstanceStatusData getSinkInstanceStatus(String tenant,
String namespace,
String sinkName,
String instanceId,
URI uri,
- String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps);
+ AuthenticationParameters authParams);
SinkStatus getSinkStatus(String tenant,
String namespace,
String componentName,
URI uri,
- String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps);
+ AuthenticationParameters authParams);
SinkConfig getSinkInfo(String tenant,
String namespace,
- String componentName);
+ String componentName,
+ AuthenticationParameters authParams);
List getSinkList();
diff --git a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/service/api/Sources.java b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/service/api/Sources.java
index 781a25e92cc87..7fe1e56bf9a13 100644
--- a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/service/api/Sources.java
+++ b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/service/api/Sources.java
@@ -21,8 +21,7 @@
import java.io.InputStream;
import java.net.URI;
import java.util.List;
-import org.apache.pulsar.broker.authentication.AuthenticationDataHttps;
-import org.apache.pulsar.broker.authentication.AuthenticationDataSource;
+import org.apache.pulsar.broker.authentication.AuthenticationParameters;
import org.apache.pulsar.common.functions.UpdateOptionsImpl;
import org.apache.pulsar.common.io.ConfigFieldDefinition;
import org.apache.pulsar.common.io.ConnectorDefinition;
@@ -46,8 +45,7 @@ public interface Sources extends Component {
* @param fileDetail A form-data content disposition header
* @param sourcePkgUrl URL path of the Pulsar Source package
* @param sourceConfig Configuration of Pulsar Source
- * @param clientRole Client role for running the Pulsar Source
- * @param clientAuthenticationDataHttps Authentication status of the http client
+ * @param authParams the authentication parameters associated with the request
*/
void registerSource(String tenant,
String namespace,
@@ -56,35 +54,7 @@ void registerSource(String tenant,
FormDataContentDisposition fileDetail,
String sourcePkgUrl,
SourceConfig sourceConfig,
- String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps);
-
- /**
- * This method uses an incorrect signature 'AuthenticationDataHttps' that prevents the extension of auth status,
- * so it is marked as deprecated and kept here only for backward compatibility. Please use the method that accepts
- * the signature of the AuthenticationDataSource.
- */
- @Deprecated
- default void registerSource(String tenant,
- String namespace,
- String sourceName,
- InputStream uploadedInputStream,
- FormDataContentDisposition fileDetail,
- String sourcePkgUrl,
- SourceConfig sourceConfig,
- String clientRole,
- AuthenticationDataHttps clientAuthenticationDataHttps) {
- registerSource(
- tenant,
- namespace,
- sourceName,
- uploadedInputStream,
- fileDetail,
- sourcePkgUrl,
- sourceConfig,
- clientRole,
- (AuthenticationDataSource) clientAuthenticationDataHttps);
- }
+ AuthenticationParameters authParams);
/**
* Update a function.
@@ -95,8 +65,7 @@ default void registerSource(String tenant,
* @param fileDetail A form-data content disposition header
* @param sourcePkgUrl URL path of the Pulsar Source package
* @param sourceConfig Configuration of Pulsar Source
- * @param clientRole Client role for running the Pulsar Source
- * @param clientAuthenticationDataHttps Authentication status of the http client
+ * @param authParams the authentication parameters associated with the request
* @param updateOptions Options while updating the source
*/
void updateSource(String tenant,
@@ -106,59 +75,26 @@ void updateSource(String tenant,
FormDataContentDisposition fileDetail,
String sourcePkgUrl,
SourceConfig sourceConfig,
- String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps,
+ AuthenticationParameters authParams,
UpdateOptionsImpl updateOptions);
- /**
- * This method uses an incorrect signature 'AuthenticationDataHttps' that prevents the extension of auth status,
- * so it is marked as deprecated and kept here only for backward compatibility. Please use the method that accepts
- * the signature of the AuthenticationDataSource.
- */
- @Deprecated
- default void updateSource(String tenant,
- String namespace,
- String sourceName,
- InputStream uploadedInputStream,
- FormDataContentDisposition fileDetail,
- String sourcePkgUrl,
- SourceConfig sourceConfig,
- String clientRole,
- AuthenticationDataHttps clientAuthenticationDataHttps,
- UpdateOptionsImpl updateOptions) {
- updateSource(
- tenant,
- namespace,
- sourceName,
- uploadedInputStream,
- fileDetail,
- sourcePkgUrl,
- sourceConfig,
- clientRole,
- (AuthenticationDataSource) clientAuthenticationDataHttps,
- updateOptions);
- }
-
-
SourceStatus getSourceStatus(String tenant,
String namespace,
String componentName,
URI uri,
- String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps);
-
+ AuthenticationParameters authParams);
SourceInstanceStatusData getSourceInstanceStatus(String tenant,
String namespace,
String sourceName,
String instanceId,
URI uri,
- String clientRole,
- AuthenticationDataSource clientAuthenticationDataHttps);
+ AuthenticationParameters authParams);
SourceConfig getSourceInfo(String tenant,
String namespace,
- String componentName);
+ String componentName,
+ AuthenticationParameters authParams);
List getSourceList();
diff --git a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/service/api/Workers.java b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/service/api/Workers.java
index a13157ea6476c..420fdcefe8b57 100644
--- a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/service/api/Workers.java
+++ b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/service/api/Workers.java
@@ -23,6 +23,7 @@
import java.util.Collection;
import java.util.List;
import java.util.Map;
+import org.apache.pulsar.broker.authentication.AuthenticationParameters;
import org.apache.pulsar.client.admin.LongRunningProcessStatus;
import org.apache.pulsar.common.functions.WorkerInfo;
import org.apache.pulsar.common.io.ConnectorDefinition;
@@ -35,25 +36,25 @@
*/
public interface Workers {
- List getCluster(String clientRole);
+ List getCluster(AuthenticationParameters authParams);
- WorkerInfo getClusterLeader(String clientRole);
+ WorkerInfo getClusterLeader(AuthenticationParameters authParams);
- Map> getAssignments(String clientRole);
+ Map> getAssignments(AuthenticationParameters authParams);
- List getWorkerMetrics(String clientRole);
+ List getWorkerMetrics(AuthenticationParameters authParams);
- List getFunctionsMetrics(String clientRole) throws IOException;
+ List getFunctionsMetrics(AuthenticationParameters authParams) throws IOException;
- List getListOfConnectors(String clientRole);
+ List getListOfConnectors(AuthenticationParameters authParams);
- void rebalance(URI uri, String clientRole);
+ void rebalance(URI uri, AuthenticationParameters authParams);
- void drain(URI uri, String workerId, String clientRole, boolean leaderUri);
+ void drain(URI uri, String workerId, AuthenticationParameters authParams, boolean leaderUri);
- LongRunningProcessStatus getDrainStatus(URI uri, String workerId, String clientRole,
+ LongRunningProcessStatus getDrainStatus(URI uri, String workerId, AuthenticationParameters authParams,
boolean leaderUri);
- Boolean isLeaderReady(String clientRole);
+ boolean isLeaderReady(AuthenticationParameters authParams);
}
diff --git a/pulsar-functions/worker/src/test/java/org/apache/pulsar/functions/worker/WorkerUtilsTest.java b/pulsar-functions/worker/src/test/java/org/apache/pulsar/functions/worker/WorkerUtilsTest.java
index c5e6b4aaded74..0f5fca4a8a5a3 100644
--- a/pulsar-functions/worker/src/test/java/org/apache/pulsar/functions/worker/WorkerUtilsTest.java
+++ b/pulsar-functions/worker/src/test/java/org/apache/pulsar/functions/worker/WorkerUtilsTest.java
@@ -33,17 +33,20 @@
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
+import java.util.HashSet;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;
import org.apache.distributedlog.DistributedLogConfiguration;
+import org.apache.pulsar.broker.ServiceConfiguration;
import org.apache.pulsar.client.api.CompressionType;
import org.apache.pulsar.client.api.Producer;
import org.apache.pulsar.client.api.ProducerAccessMode;
import org.apache.pulsar.client.api.ProducerBuilder;
import org.apache.pulsar.client.api.PulsarClient;
import org.apache.pulsar.client.api.PulsarClientException;
+import org.apache.pulsar.common.configuration.PulsarConfigurationLoader;
import org.testng.annotations.Test;
public class WorkerUtilsTest {
@@ -118,4 +121,15 @@ public void testDLogConfiguration() throws URISyntaxException, IOException {
assertEquals(dlogConf.getString("bkc.testKey"), "fakeValue",
"The bookkeeper client config mapping should apply.");
}
+
+ @Test
+ public void testProxyRolesInWorkerConfigMapToServiceConfiguration() throws Exception {
+ URL yamlUrl = getClass().getClassLoader().getResource("test_worker_config.yml");
+ WorkerConfig wc = WorkerConfig.load(yamlUrl.toURI().getPath());
+ ServiceConfiguration conf = PulsarConfigurationLoader.convertFrom(wc);
+ HashSet proxyRoles = new HashSet<>();
+ proxyRoles.add("proxyA");
+ proxyRoles.add("proxyB");
+ assertEquals(conf.getProxyRoles(), proxyRoles);
+ }
}
diff --git a/pulsar-functions/worker/src/test/java/org/apache/pulsar/functions/worker/rest/api/FunctionsImplTest.java b/pulsar-functions/worker/src/test/java/org/apache/pulsar/functions/worker/rest/api/FunctionsImplTest.java
index 998d85683e204..cfe087c78406a 100644
--- a/pulsar-functions/worker/src/test/java/org/apache/pulsar/functions/worker/rest/api/FunctionsImplTest.java
+++ b/pulsar-functions/worker/src/test/java/org/apache/pulsar/functions/worker/rest/api/FunctionsImplTest.java
@@ -18,7 +18,6 @@
*/
package org.apache.pulsar.functions.worker.rest.api;
-import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.doReturn;
@@ -28,27 +27,39 @@
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertThrows;
import static org.testng.Assert.assertTrue;
import java.io.InputStream;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
import org.apache.distributedlog.api.namespace.Namespace;
import org.apache.pulsar.broker.authentication.AuthenticationDataSource;
+import org.apache.pulsar.broker.authentication.AuthenticationParameters;
import org.apache.pulsar.broker.authorization.AuthorizationService;
+import org.apache.pulsar.broker.resources.NamespaceResources;
+import org.apache.pulsar.broker.resources.PulsarResources;
+import org.apache.pulsar.broker.resources.TenantResources;
import org.apache.pulsar.client.admin.Namespaces;
import org.apache.pulsar.client.admin.PulsarAdmin;
import org.apache.pulsar.client.admin.PulsarAdminException;
import org.apache.pulsar.client.admin.Tenants;
import org.apache.pulsar.client.api.PulsarClientException;
+import org.apache.pulsar.common.configuration.PulsarConfigurationLoader;
import org.apache.pulsar.common.functions.FunctionConfig;
+import org.apache.pulsar.common.naming.NamespaceName;
+import org.apache.pulsar.common.policies.data.AuthAction;
import org.apache.pulsar.common.policies.data.FunctionInstanceStatsImpl;
import org.apache.pulsar.common.policies.data.FunctionStatsImpl;
+import org.apache.pulsar.common.policies.data.Policies;
import org.apache.pulsar.common.policies.data.TenantInfo;
+import org.apache.pulsar.common.util.RestException;
import org.apache.pulsar.functions.api.Context;
import org.apache.pulsar.functions.instance.InstanceConfig;
import org.apache.pulsar.functions.instance.JavaInstanceRunnable;
@@ -94,6 +105,7 @@ public String process(String input, Context context) {
private static final int parallelism = 1;
private static final String workerId = "worker-0";
private static final String superUser = "superUser";
+ private static final String proxyUser = "proxyUser";
private PulsarWorkerService mockedWorkerService;
private PulsarAdmin mockedPulsarAdmin;
@@ -196,7 +208,7 @@ public void cleanup() {
@Test
public void testStatusEmpty() {
- assertNotNull(this.resource.getFunctionInstanceStatus(tenant, namespace, function, "0", null, null, null));
+ assertNotNull(this.resource.getFunctionInstanceStatus(tenant, namespace, function, "0", null, null));
}
@Test
@@ -231,83 +243,80 @@ public void testMetricsEmpty() throws PulsarClientException {
assertNotNull(functionStats.calculateOverall());
}
+ // Suppress the deprecation warnings until we actually remove the deprecated method
+ @SuppressWarnings("deprecation")
@Test
- public void testIsAuthorizedRole() throws PulsarAdminException, InterruptedException, ExecutionException {
+ public void testIsAuthorizedRole() throws Exception {
- TenantInfo tenantInfo = TenantInfo.builder().build();
AuthenticationDataSource authenticationDataSource = mock(AuthenticationDataSource.class);
FunctionsImpl functionImpl = spy(new FunctionsImpl(() -> mockedWorkerService));
- AuthorizationService authorizationService = mock(AuthorizationService.class);
- doReturn(authorizationService).when(mockedWorkerService).getAuthorizationService();
WorkerConfig workerConfig = new WorkerConfig();
workerConfig.setAuthorizationEnabled(true);
- workerConfig.setSuperUserRoles(Collections.singleton(superUser));
+ HashSet superUsers = new HashSet<>();
+ superUsers.add(superUser);
+ superUsers.add(proxyUser);
+ workerConfig.setSuperUserRoles(superUsers);
+ workerConfig.setProxyRoles(Collections.singleton(proxyUser));
+ // TODO remove mocking by relying on TestPulsarResources. Can't do now because this commit needs to be
+ // cherry picked back.
+ PulsarResources pulsarResources = mock(PulsarResources.class);
+ TenantResources tenantResources = mock(TenantResources.class);
+ when(pulsarResources.getTenantResources()).thenReturn(tenantResources);
+ TenantInfo tenantInfo = TenantInfo.builder().adminRoles(Collections.singleton("tenant-admin")).build();
+ when(tenantResources.getTenantAsync("test-tenant"))
+ .thenReturn(CompletableFuture.completedFuture(Optional.of(tenantInfo)));
+ NamespaceResources namespaceResources = mock(NamespaceResources.class);
+ when(pulsarResources.getNamespaceResources()).thenReturn(namespaceResources);
+ Policies p = new Policies();
+ p.auth_policies.getNamespaceAuthentication().put("test-function-user", Set.of(AuthAction.functions));
+ when(namespaceResources.getPoliciesAsync(NamespaceName.get("test-tenant/test-ns")))
+ .thenReturn(CompletableFuture.completedFuture(Optional.of(p)));
+
+ AuthorizationService authorizationService = new AuthorizationService(
+ PulsarConfigurationLoader.convertFrom(workerConfig), pulsarResources);
doReturn(workerConfig).when(mockedWorkerService).getWorkerConfig();
+ doReturn(authorizationService).when(mockedWorkerService).getAuthorizationService();
// test super user
- assertTrue(functionImpl.isAuthorizedRole("test-tenant", "test-ns", superUser, authenticationDataSource));
-
- // test pulsar super user
- final String pulsarSuperUser = "pulsarSuperUser";
- when(authorizationService.isSuperUser(eq(pulsarSuperUser), any()))
- .thenReturn(CompletableFuture.completedFuture(true));
- assertTrue(functionImpl.isAuthorizedRole("test-tenant", "test-ns", pulsarSuperUser, authenticationDataSource));
- assertTrue(functionImpl.isSuperUser(pulsarSuperUser, null));
+ assertTrue(functionImpl.isAuthorizedRole("test-tenant", "test-ns", superUser,
+ authenticationDataSource));
+ assertTrue(functionImpl.isSuperUser(superUser, null));
- // test normal user
- functionImpl = spy(new FunctionsImpl(() -> mockedWorkerService));
- doReturn(false).when(functionImpl).allowFunctionOps(any(), any(), any());
- Tenants tenants = mock(Tenants.class);
- when(tenants.getTenantInfo(any())).thenReturn(tenantInfo);
- PulsarAdmin admin = mock(PulsarAdmin.class);
- when(admin.tenants()).thenReturn(tenants);
- when(this.mockedWorkerService.getBrokerAdmin()).thenReturn(admin);
- when(authorizationService.isTenantAdmin("test-tenant", "test-user", tenantInfo, authenticationDataSource))
- .thenReturn(CompletableFuture.completedFuture(false));
- when(authorizationService.isSuperUser(eq("test-user"), any()))
- .thenReturn(CompletableFuture.completedFuture(false));
- assertFalse(functionImpl.isAuthorizedRole("test-tenant", "test-ns", "test-user", authenticationDataSource));
+ // test normal user with no permissions
+ assertFalse(functionImpl.isAuthorizedRole("test-tenant", "test-ns", "test-non-admin-user",
+ authenticationDataSource));
// if user is tenant admin
- functionImpl = spy(new FunctionsImpl(() -> mockedWorkerService));
- doReturn(false).when(functionImpl).allowFunctionOps(any(), any(), any());
- tenants = mock(Tenants.class);
- tenantInfo = TenantInfo.builder().adminRoles(Collections.singleton("test-user")).build();
- when(tenants.getTenantInfo(any())).thenReturn(tenantInfo);
-
- admin = mock(PulsarAdmin.class);
- when(admin.tenants()).thenReturn(tenants);
- when(this.mockedWorkerService.getBrokerAdmin()).thenReturn(admin);
- when(authorizationService.isTenantAdmin("test-tenant", "test-user", tenantInfo, authenticationDataSource))
- .thenReturn(CompletableFuture.completedFuture(true));
- when(authorizationService.isSuperUser("test-user", authenticationDataSource))
- .thenReturn(CompletableFuture.completedFuture(false));
- assertTrue(functionImpl.isAuthorizedRole("test-tenant", "test-ns", "test-user", authenticationDataSource));
+ assertTrue(functionImpl.isAuthorizedRole("test-tenant", "test-ns", "tenant-admin",
+ authenticationDataSource));
// test user allow function action
- functionImpl = spy(new FunctionsImpl(() -> mockedWorkerService));
- doReturn(true).when(functionImpl).allowFunctionOps(any(), any(), any());
- tenants = mock(Tenants.class);
- tenantInfo = TenantInfo.builder().build();
- when(tenants.getTenantInfo(any())).thenReturn(tenantInfo);
-
- admin = mock(PulsarAdmin.class);
- when(admin.tenants()).thenReturn(tenants);
- when(this.mockedWorkerService.getBrokerAdmin()).thenReturn(admin);
- when(authorizationService.isTenantAdmin("test-tenant", "test-user", tenantInfo, authenticationDataSource))
- .thenReturn(CompletableFuture.completedFuture(true));
- assertTrue(functionImpl.isAuthorizedRole("test-tenant", "test-ns", "test-user", authenticationDataSource));
+ assertTrue(functionImpl.isAuthorizedRole("test-tenant", "test-ns", "test-function-user",
+ authenticationDataSource));
// test role is null
- functionImpl = spy(new FunctionsImpl(() -> mockedWorkerService));
- doReturn(true).when(functionImpl).allowFunctionOps(any(), any(), any());
- tenants = mock(Tenants.class);
- when(tenants.getTenantInfo(any())).thenReturn(TenantInfo.builder().build());
-
- admin = mock(PulsarAdmin.class);
- when(admin.tenants()).thenReturn(tenants);
- when(this.mockedWorkerService.getBrokerAdmin()).thenReturn(admin);
- assertFalse(functionImpl.isAuthorizedRole("test-tenant", "test-ns", null, authenticationDataSource));
+ assertThrows(RestException.class, () -> functionImpl.isAuthorizedRole("test-tenant",
+ "test-ns", null, authenticationDataSource));
+
+ // test proxy user with no original principal
+ assertFalse(functionImpl.isAuthorizedRole("test-tenant", "test-ns",
+ AuthenticationParameters.builder().clientRole(proxyUser).build()));
+
+ // test proxy user with tenant admin original principal
+ assertTrue(functionImpl.isAuthorizedRole("test-tenant", "test-ns",
+ AuthenticationParameters.builder().clientRole(proxyUser).originalPrincipal("tenant-admin").build()));
+
+ // test proxy user with non admin user
+ assertFalse(functionImpl.isAuthorizedRole("test-tenant", "test-ns",
+ AuthenticationParameters.builder().clientRole(proxyUser).originalPrincipal("test-non-admin-user").build()));
+
+ // test proxy user with allow function action
+ assertTrue(functionImpl.isAuthorizedRole("test-tenant", "test-ns",
+ AuthenticationParameters.builder().clientRole(proxyUser).originalPrincipal("test-function-user").build()));
+
+ // test non-proxy user passing original principal
+ assertFalse(functionImpl.isAuthorizedRole("test-tenant", "test-ns",
+ AuthenticationParameters.builder().clientRole("nobody").originalPrincipal("test-non-admin-user").build()));
}
@Test
@@ -320,20 +329,19 @@ public void testIsSuperUser() throws PulsarAdminException {
workerConfig.setAuthorizationEnabled(true);
workerConfig.setSuperUserRoles(Collections.singleton(superUser));
doReturn(workerConfig).when(mockedWorkerService).getWorkerConfig();
- when(authorizationService.isSuperUser(anyString(), any()))
+ when(authorizationService.isSuperUser(any(AuthenticationParameters.class)))
.thenAnswer((invocationOnMock) -> {
- String role = invocationOnMock.getArgument(0, String.class);
+ String role = invocationOnMock.getArgument(0, AuthenticationParameters.class).getClientRole();
return CompletableFuture.completedFuture(superUser.equals(role));
});
- AuthenticationDataSource authenticationDataSource = mock(AuthenticationDataSource.class);
assertTrue(functionImpl.isSuperUser(superUser, null));
assertFalse(functionImpl.isSuperUser("normal-user", null));
assertFalse(functionImpl.isSuperUser(null, null));
// test super roles is null and it's not a pulsar super user
- when(authorizationService.isSuperUser(superUser, null))
+ when(authorizationService.isSuperUser(AuthenticationParameters.builder().clientRole(superUser).build()))
.thenReturn(CompletableFuture.completedFuture(false));
functionImpl = spy(new FunctionsImpl(() -> mockedWorkerService));
workerConfig = new WorkerConfig();
@@ -342,10 +350,10 @@ public void testIsSuperUser() throws PulsarAdminException {
assertFalse(functionImpl.isSuperUser(superUser, null));
// test super role is null but the auth datasource contains superuser
- when(authorizationService.isSuperUser(anyString(), any(AuthenticationDataSource.class)))
+ when(authorizationService.isSuperUser(any(AuthenticationParameters.class)))
.thenAnswer((invocationOnMock -> {
- AuthenticationDataSource authData = invocationOnMock.getArgument(1, AuthenticationDataSource.class);
- String user = authData.getHttpHeader("mockedUser");
+ AuthenticationParameters authData = invocationOnMock.getArgument(0, AuthenticationParameters.class);
+ String user = authData.getClientAuthenticationDataSource().getHttpHeader("mockedUser");
return CompletableFuture.completedFuture(superUser.equals(user));
}));
AuthenticationDataSource authData = mock(AuthenticationDataSource.class);
diff --git a/pulsar-functions/worker/src/test/java/org/apache/pulsar/functions/worker/rest/api/WorkerImplTest.java b/pulsar-functions/worker/src/test/java/org/apache/pulsar/functions/worker/rest/api/WorkerImplTest.java
new file mode 100644
index 0000000000000..eb7228383552c
--- /dev/null
+++ b/pulsar-functions/worker/src/test/java/org/apache/pulsar/functions/worker/rest/api/WorkerImplTest.java
@@ -0,0 +1,120 @@
+/*
+ * 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.pulsar.functions.worker.rest.api;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+import java.util.HashSet;
+import org.apache.pulsar.broker.authentication.AuthenticationParameters;
+import org.apache.pulsar.broker.authorization.AuthorizationService;
+import org.apache.pulsar.broker.resources.PulsarResources;
+import org.apache.pulsar.common.configuration.PulsarConfigurationLoader;
+import org.apache.pulsar.common.util.RestException;
+import org.apache.pulsar.functions.worker.LeaderService;
+import org.apache.pulsar.functions.worker.MetricsGenerator;
+import org.apache.pulsar.functions.worker.PulsarWorkerService;
+import org.apache.pulsar.functions.worker.WorkerConfig;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/**
+ * Unit test of {@link WorkerImpl} to ensure that all methods properly fail if the {@link AuthenticationParameters}
+ * do not represent a superuser.
+ */
+public class WorkerImplTest {
+ WorkerImpl worker;
+
+ @DataProvider(name = "authParamsForNonSuperusers")
+ public Object[][] partitionedTopicProvider() {
+ return new Object[][] {
+ { AuthenticationParameters.builder().build() }, // all fields null should fail
+ { AuthenticationParameters.builder().clientRole("user").build() }, // Not superuser, no proxy
+ { AuthenticationParameters.builder()
+ .clientRole("proxySuperuser").build() }, // Proxy role needs original principal
+ { AuthenticationParameters.builder()
+ .clientRole("proxyNotSuperuser").build() }, // Proxy role needs original principal
+ { AuthenticationParameters.builder().clientRole("proxyNotSuperuser")
+ .originalPrincipal("superuser").build() }, // Proxy is not superuser
+ { AuthenticationParameters.builder().clientRole("proxyNotSuperuser")
+ .originalPrincipal("user").build() }, // Neither proxy nor original principal is superuser
+ { AuthenticationParameters.builder().clientRole("proxySuperuser")
+ .originalPrincipal("user").build() }, // Original principal is not superuser
+ { AuthenticationParameters.builder().clientRole("user")
+ .originalPrincipal("superuser").build() }, // User is not a proxyRole
+ { AuthenticationParameters.builder().clientRole("superuser2")
+ .originalPrincipal("superuser").build() }, // Both are superusers, but client is not a proxyRole
+ };
+ }
+
+ @BeforeClass
+ void setup() throws Exception {
+ WorkerConfig config = new WorkerConfig();
+ config.setPulsarFunctionsCluster("testThrowIfNotSuperUserFailures");
+ config.setAuthorizationEnabled(true);
+ HashSet proxyRoles = new HashSet<>();
+ proxyRoles.add("proxySuperuser");
+ proxyRoles.add("proxyNotSuperuser");
+ HashSet superUserRoles = new HashSet<>();
+ superUserRoles.add("superuser");
+ superUserRoles.add("superuser2");
+ superUserRoles.add("proxySuperuser");
+ config.setSuperUserRoles(superUserRoles);
+ config.setProxyRoles(proxyRoles);
+ AuthorizationService authorizationService = new AuthorizationService(
+ PulsarConfigurationLoader.convertFrom(config), mock(PulsarResources.class));
+ PulsarWorkerService pulsarWorkerService = mock(PulsarWorkerService.class);
+ when(pulsarWorkerService.getWorkerConfig()).thenReturn(config);
+ when(pulsarWorkerService.getAuthorizationService()).thenReturn(authorizationService);
+ when(pulsarWorkerService.isInitialized()).thenReturn(true);
+ when(pulsarWorkerService.getMetricsGenerator()).thenReturn(mock(MetricsGenerator.class));
+ LeaderService leaderService = mock(LeaderService.class);
+ when(leaderService.isLeader()).thenReturn(true);
+ when(pulsarWorkerService.getLeaderService()).thenReturn(leaderService);
+ worker = new WorkerImpl(() -> pulsarWorkerService);
+ }
+
+ @Test(dataProvider = "authParamsForNonSuperusers")
+ public void ensureNonSuperuserCombinationsFailAuthorization(AuthenticationParameters authParams) throws Throwable {
+ assertThrowsRestException401(() -> worker.getCluster(authParams));
+ assertThrowsRestException401(() -> worker.getClusterLeader(authParams));
+ assertThrowsRestException401(() -> worker.getAssignments(authParams));
+ assertThrowsRestException401(() -> worker.getWorkerMetrics(authParams));
+ assertThrowsRestException401(() -> worker.getFunctionsMetrics(authParams));
+ assertThrowsRestException401(() -> worker.getListOfConnectors(authParams));
+ assertThrowsRestException401(() -> worker.rebalance(null, authParams));
+ assertThrowsRestException401(() -> worker.drain(null, "test", authParams, false));
+ assertThrowsRestException401(() -> worker.getDrainStatus(null, "test", authParams, false));
+ // This endpoint is not protected
+ assertTrue(worker.isLeaderReady(authParams));
+ }
+
+ private void assertThrowsRestException401(Assert.ThrowingRunnable runnable) throws Throwable {
+ try {
+ runnable.run();
+ fail("Should have thrown RestException");
+ } catch (RestException e) {
+ assertEquals(e.getResponse().getStatus(), 401);
+ }
+ }
+}
diff --git a/pulsar-functions/worker/src/test/java/org/apache/pulsar/functions/worker/rest/api/v2/FunctionApiV2ResourceTest.java b/pulsar-functions/worker/src/test/java/org/apache/pulsar/functions/worker/rest/api/v2/FunctionApiV2ResourceTest.java
index 80b626165a5d8..32a104c576993 100644
--- a/pulsar-functions/worker/src/test/java/org/apache/pulsar/functions/worker/rest/api/v2/FunctionApiV2ResourceTest.java
+++ b/pulsar-functions/worker/src/test/java/org/apache/pulsar/functions/worker/rest/api/v2/FunctionApiV2ResourceTest.java
@@ -53,6 +53,7 @@
import org.apache.distributedlog.api.namespace.Namespace;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.config.Configurator;
+import org.apache.pulsar.broker.authentication.AuthenticationParameters;
import org.apache.pulsar.client.admin.Functions;
import org.apache.pulsar.client.admin.Namespaces;
import org.apache.pulsar.client.admin.PulsarAdmin;
@@ -542,7 +543,7 @@ private void testRegisterFunctionMissingArguments(
details,
functionPkgUrl,
JsonFormat.printer().print(FunctionConfigUtils.convert(functionConfig, (ClassLoader) null)),
- null);
+ AuthenticationParameters.builder().build());
} catch (InvalidProtocolBufferException e) {
throw new RuntimeException(e);
}
@@ -560,7 +561,7 @@ private void registerDefaultFunction() {
mockedFormData,
null,
JsonFormat.printer().print(FunctionConfigUtils.convert(functionConfig, (ClassLoader) null)),
- null);
+ AuthenticationParameters.builder().build());
} catch (InvalidProtocolBufferException e) {
throw new RuntimeException(e);
}
@@ -943,7 +944,7 @@ private void testUpdateFunctionMissingArguments(
details,
null,
JsonFormat.printer().print(FunctionConfigUtils.convert(functionConfig, (ClassLoader) null)),
- null);
+ AuthenticationParameters.builder().build());
} catch (InvalidProtocolBufferException e) {
throw new RuntimeException(e);
}
@@ -971,7 +972,7 @@ private void updateDefaultFunction() {
mockedFormData,
null,
JsonFormat.printer().print(FunctionConfigUtils.convert(functionConfig, (ClassLoader) null)),
- null);
+ AuthenticationParameters.builder().build());
} catch (InvalidProtocolBufferException e) {
throw new RuntimeException(e);
}
@@ -1048,7 +1049,7 @@ public void testUpdateFunctionWithUrl() throws Exception {
null,
filePackageUrl,
JsonFormat.printer().print(FunctionConfigUtils.convert(functionConfig, (ClassLoader) null)),
- null);
+ AuthenticationParameters.builder().build());
} catch (InvalidProtocolBufferException e) {
throw new RuntimeException(e);
}
@@ -1144,7 +1145,7 @@ private void testDeregisterFunctionMissingArguments(
tenant,
namespace,
function,
- null);
+ AuthenticationParameters.builder().build());
}
private void deregisterDefaultFunction() {
@@ -1152,7 +1153,7 @@ private void deregisterDefaultFunction() {
tenant,
namespace,
function,
- null);
+ AuthenticationParameters.builder().build());
}
@Test(expectedExceptions = RestException.class, expectedExceptionsMessageRegExp = "Function test-function doesn't exist")
@@ -1257,7 +1258,8 @@ private void testGetFunctionMissingArguments(
resource.getFunctionInfo(
tenant,
namespace,
- function, null
+ function,
+ AuthenticationParameters.builder().build()
);
}
@@ -1266,7 +1268,8 @@ private FunctionDetails getDefaultFunctionInfo() throws IOException {
String json = (String) resource.getFunctionInfo(
tenant,
namespace,
- function, null
+ function,
+ AuthenticationParameters.builder().build()
).getEntity();
FunctionDetails.Builder functionDetailsBuilder = FunctionDetails.newBuilder();
mergeJson(json, functionDetailsBuilder);
@@ -1353,7 +1356,8 @@ private void testListFunctionsMissingArguments(
) {
resource.listFunctions(
tenant,
- namespace, null
+ namespace,
+ AuthenticationParameters.builder().build()
);
}
@@ -1361,7 +1365,8 @@ private void testListFunctionsMissingArguments(
private List listDefaultFunctions() {
return new Gson().fromJson((String) resource.listFunctions(
tenant,
- namespace, null
+ namespace,
+ AuthenticationParameters.builder().build()
).getEntity(), List.class);
}
@@ -1390,7 +1395,8 @@ public void testDownloadFunctionHttpUrl() throws Exception {
"https://repo1.maven.org/maven2/org/apache/pulsar/pulsar-common/2.4.2/pulsar-common-2.4.2.jar";
String testDir = FunctionApiV2ResourceTest.class.getProtectionDomain().getCodeSource().getLocation().getPath();
FunctionsImplV2 function = new FunctionsImplV2(() -> mockedWorkerService);
- StreamingOutput streamOutput = (StreamingOutput) function.downloadFunction(jarHttpUrl, null).getEntity();
+ StreamingOutput streamOutput = (StreamingOutput) function.downloadFunction(jarHttpUrl,
+ AuthenticationParameters.builder().build()).getEntity();
File pkgFile = new File(testDir, UUID.randomUUID().toString());
OutputStream output = new FileOutputStream(pkgFile);
streamOutput.write(output);
@@ -1407,8 +1413,8 @@ public void testDownloadFunctionFile() throws Exception {
String fileLocation = file.getAbsolutePath().replace('\\', '/');
String testDir = FunctionApiV2ResourceTest.class.getProtectionDomain().getCodeSource().getLocation().getPath();
FunctionsImplV2 function = new FunctionsImplV2(() -> mockedWorkerService);
- StreamingOutput streamOutput =
- (StreamingOutput) function.downloadFunction("file:///" + fileLocation, null).getEntity();
+ StreamingOutput streamOutput = (StreamingOutput) function.downloadFunction("file:///" + fileLocation,
+ AuthenticationParameters.builder().build()).getEntity();
File pkgFile = new File(testDir, UUID.randomUUID().toString());
OutputStream output = new FileOutputStream(pkgFile);
streamOutput.write(output);
@@ -1440,7 +1446,8 @@ public void testRegisterFunctionFileUrlWithValidSinkClass() throws Exception {
functionConfig.setOutputSerdeClassName(outputSerdeClassName);
try {
resource.registerFunction(tenant, namespace, function, null, null, filePackageUrl,
- JsonFormat.printer().print(FunctionConfigUtils.convert(functionConfig, (ClassLoader) null)), null);
+ JsonFormat.printer().print(FunctionConfigUtils.convert(functionConfig, (ClassLoader) null)),
+ AuthenticationParameters.builder().build());
} catch (InvalidProtocolBufferException e) {
throw new RuntimeException(e);
}
@@ -1474,7 +1481,8 @@ public void testRegisterFunctionWithConflictingFields() throws Exception {
functionConfig.setOutputSerdeClassName(outputSerdeClassName);
try {
resource.registerFunction(actualTenant, actualNamespace, actualName, null, null, filePackageUrl,
- JsonFormat.printer().print(FunctionConfigUtils.convert(functionConfig, (ClassLoader) null)), null);
+ JsonFormat.printer().print(FunctionConfigUtils.convert(functionConfig, (ClassLoader) null)),
+ AuthenticationParameters.builder().build());
} catch (InvalidProtocolBufferException e) {
throw new RuntimeException(e);
}
diff --git a/pulsar-functions/worker/src/test/java/org/apache/pulsar/functions/worker/rest/api/v3/FunctionApiV3ResourceTest.java b/pulsar-functions/worker/src/test/java/org/apache/pulsar/functions/worker/rest/api/v3/FunctionApiV3ResourceTest.java
index c34b26180f876..337999bf2ad5e 100644
--- a/pulsar-functions/worker/src/test/java/org/apache/pulsar/functions/worker/rest/api/v3/FunctionApiV3ResourceTest.java
+++ b/pulsar-functions/worker/src/test/java/org/apache/pulsar/functions/worker/rest/api/v3/FunctionApiV3ResourceTest.java
@@ -49,6 +49,7 @@
import org.apache.distributedlog.api.namespace.Namespace;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.config.Configurator;
+import org.apache.pulsar.broker.authentication.AuthenticationParameters;
import org.apache.pulsar.client.admin.Functions;
import org.apache.pulsar.client.admin.Namespaces;
import org.apache.pulsar.client.admin.Packages;
@@ -571,7 +572,7 @@ private void testRegisterFunctionMissingArguments(
details,
functionPkgUrl,
functionConfig,
- null, null);
+ null);
}
@@ -585,7 +586,7 @@ public void testMissingFunctionConfig() {
mockedFormData,
null,
null,
- null, null);
+ null);
}
@Test(expectedExceptions = RestException.class, expectedExceptionsMessageRegExp = "Function config is not provided")
@@ -600,7 +601,7 @@ public void testUpdateMissingFunctionConfig() {
mockedFormData,
null,
null,
- null, null, null);
+ null, null);
}
private void registerDefaultFunction() {
@@ -617,7 +618,7 @@ private void registerDefaultFunctionWithPackageUrl(String packageUrl) {
mockedFormData,
packageUrl,
functionConfig,
- null, null);
+ null);
}
@Test(expectedExceptions = RestException.class, expectedExceptionsMessageRegExp = "Function test-function already exists")
@@ -795,7 +796,7 @@ public void testRegisterFunctionSuccessK8sNoUpload() throws Exception {
mockedFormData,
null,
functionConfig,
- null, null);
+ null);
}
}
@@ -852,7 +853,7 @@ public void testRegisterFunctionSuccessK8sWithUpload() throws Exception {
mockedFormData,
null,
functionConfig,
- null, null);
+ null);
Assert.fail();
} catch (RuntimeException e) {
Assert.assertEquals(e.getMessage(), injectedErrMsg);
@@ -1115,7 +1116,7 @@ private void testUpdateFunctionMissingArguments(
details,
null,
functionConfig,
- null, null, null);
+ null, null);
}
@@ -1143,7 +1144,7 @@ private void updateDefaultFunctionWithPackageUrl(String packageUrl) {
mockedFormData,
packageUrl,
functionConfig,
- null, null, null);
+ null, null);
}
@Test(expectedExceptions = RestException.class, expectedExceptionsMessageRegExp = "Function test-function doesn't exist")
@@ -1217,7 +1218,7 @@ public void testUpdateFunctionWithUrl() {
null,
filePackageUrl,
functionConfig,
- null, null, null);
+ null, null);
}
@@ -1331,7 +1332,7 @@ private void testDeregisterFunctionMissingArguments(
tenant,
namespace,
function,
- null, null);
+ null);
}
private void deregisterDefaultFunction() {
@@ -1339,7 +1340,7 @@ private void deregisterDefaultFunction() {
tenant,
namespace,
function,
- null, null);
+ null);
}
@Test(expectedExceptions = RestException.class, expectedExceptionsMessageRegExp = "Function test-function doesn't exist")
@@ -1444,7 +1445,7 @@ private void testGetFunctionMissingArguments(
resource.getFunctionInfo(
tenant,
namespace,
- function,null,null
+ function,null
);
}
@@ -1454,7 +1455,6 @@ private FunctionConfig getDefaultFunctionInfo() {
tenant,
namespace,
function,
- null,
null
);
}
@@ -1539,7 +1539,7 @@ private void testListFunctionsMissingArguments(
) {
resource.listFunctions(
tenant,
- namespace,null,null
+ namespace,null
);
}
@@ -1547,7 +1547,7 @@ private void testListFunctionsMissingArguments(
private List listDefaultFunctions() {
return resource.listFunctions(
tenant,
- namespace,null,null
+ namespace,null
);
}
@@ -1604,7 +1604,7 @@ public void testDownloadFunctionHttpUrl() throws Exception {
"https://repo1.maven.org/maven2/org/apache/pulsar/pulsar-common/2.4.2/pulsar-common-2.4.2.jar";
String testDir = FunctionApiV3ResourceTest.class.getProtectionDomain().getCodeSource().getLocation().getPath();
- StreamingOutput streamOutput = resource.downloadFunction(jarHttpUrl, null, null);
+ StreamingOutput streamOutput = resource.downloadFunction(jarHttpUrl, null);
File pkgFile = new File(testDir, UUID.randomUUID().toString());
OutputStream output = new FileOutputStream(pkgFile);
streamOutput.write(output);
@@ -1619,7 +1619,7 @@ public void testDownloadFunctionFile() throws Exception {
String fileLocation = file.getAbsolutePath().replace('\\', '/');
String testDir = FunctionApiV3ResourceTest.class.getProtectionDomain().getCodeSource().getLocation().getPath();
- StreamingOutput streamOutput = resource.downloadFunction("file:///" + fileLocation, null, null);
+ StreamingOutput streamOutput = resource.downloadFunction("file:///" + fileLocation, null);
File pkgFile = new File(testDir, UUID.randomUUID().toString());
OutputStream output = new FileOutputStream(pkgFile);
streamOutput.write(output);
@@ -1643,7 +1643,7 @@ public void testDownloadFunctionBuiltinConnector() throws Exception {
when(connectorsManager.getConnector("cassandra")).thenReturn(connector);
when(mockedWorkerService.getConnectorsManager()).thenReturn(connectorsManager);
- StreamingOutput streamOutput = resource.downloadFunction("builtin://cassandra", null, null);
+ StreamingOutput streamOutput = resource.downloadFunction("builtin://cassandra", null);
File pkgFile = new File(testDir, UUID.randomUUID().toString());
OutputStream output = new FileOutputStream(pkgFile);
@@ -1672,7 +1672,7 @@ public void testDownloadFunctionBuiltinFunction() throws Exception {
when(mockedWorkerService.getConnectorsManager()).thenReturn(mock(ConnectorsManager.class));
when(mockedWorkerService.getFunctionsManager()).thenReturn(functionsManager);
- StreamingOutput streamOutput = resource.downloadFunction("builtin://exclamation", null, null);
+ StreamingOutput streamOutput = resource.downloadFunction("builtin://exclamation", null);
File pkgFile = new File(testDir, UUID.randomUUID().toString());
OutputStream output = new FileOutputStream(pkgFile);
@@ -1707,7 +1707,8 @@ public void testDownloadFunctionBuiltinConnectorByName() throws Exception {
when(connectorsManager.getConnector("cassandra")).thenReturn(connector);
when(mockedWorkerService.getConnectorsManager()).thenReturn(connectorsManager);
- StreamingOutput streamOutput = resource.downloadFunction(tenant, namespace, function, null, null, false);
+ StreamingOutput streamOutput = resource.downloadFunction(tenant, namespace, function,
+ AuthenticationParameters.builder().build(), false);
File pkgFile = new File(testDir, UUID.randomUUID().toString());
OutputStream output = new FileOutputStream(pkgFile);
streamOutput.write(output);
@@ -1740,7 +1741,8 @@ public void testDownloadFunctionBuiltinFunctionByName() throws Exception {
when(mockedWorkerService.getConnectorsManager()).thenReturn(mock(ConnectorsManager.class));
when(mockedWorkerService.getFunctionsManager()).thenReturn(functionsManager);
- StreamingOutput streamOutput = resource.downloadFunction(tenant, namespace, function, null, null, false);
+ StreamingOutput streamOutput = resource.downloadFunction(tenant, namespace, function,
+ AuthenticationParameters.builder().build(), false);
File pkgFile = new File(testDir, UUID.randomUUID().toString());
OutputStream output = new FileOutputStream(pkgFile);
streamOutput.write(output);
@@ -1774,7 +1776,8 @@ public void testDownloadTransformFunctionByName() throws Exception {
when(mockedWorkerService.getConnectorsManager()).thenReturn(mock(ConnectorsManager.class));
when(mockedWorkerService.getFunctionsManager()).thenReturn(functionsManager);
- StreamingOutput streamOutput = resource.downloadFunction(tenant, namespace, function, null, null, true);
+ StreamingOutput streamOutput = resource.downloadFunction(tenant, namespace, function,
+ AuthenticationParameters.builder().build(), true);
File pkgFile = new File(testDir, UUID.randomUUID().toString());
OutputStream output = new FileOutputStream(pkgFile);
streamOutput.write(output);
@@ -1804,7 +1807,7 @@ public void testRegisterFunctionFileUrlWithValidSinkClass() throws Exception {
functionConfig.setCustomSerdeInputs(topicsToSerDeClassName);
functionConfig.setOutput(outputTopic);
functionConfig.setOutputSerdeClassName(outputSerdeClassName);
- resource.registerFunction(tenant, namespace, function, null, null, filePackageUrl, functionConfig, null, null);
+ resource.registerFunction(tenant, namespace, function, null, null, filePackageUrl, functionConfig, null);
}
@@ -1834,7 +1837,7 @@ public void testRegisterFunctionWithConflictingFields() throws Exception {
functionConfig.setOutput(outputTopic);
functionConfig.setOutputSerdeClassName(outputSerdeClassName);
resource.registerFunction(actualTenant, actualNamespace, actualName, null, null, filePackageUrl, functionConfig,
- null, null);
+ null);
}
@Test(expectedExceptions = RestException.class, expectedExceptionsMessageRegExp = "Function language runtime is either not set or cannot be determined")
@@ -1856,7 +1859,7 @@ public void testCreateFunctionWithoutSettingRuntime() throws Exception {
functionConfig.setCustomSerdeInputs(topicsToSerDeClassName);
functionConfig.setOutput(outputTopic);
functionConfig.setOutputSerdeClassName(outputSerdeClassName);
- resource.registerFunction(tenant, namespace, function, null, null, filePackageUrl, functionConfig, null, null);
+ resource.registerFunction(tenant, namespace, function, null, null, filePackageUrl, functionConfig, null);
}
diff --git a/pulsar-functions/worker/src/test/java/org/apache/pulsar/functions/worker/rest/api/v3/SinkApiV3ResourceTest.java b/pulsar-functions/worker/src/test/java/org/apache/pulsar/functions/worker/rest/api/v3/SinkApiV3ResourceTest.java
index 9f0de2a12e091..9f786c5b73aac 100644
--- a/pulsar-functions/worker/src/test/java/org/apache/pulsar/functions/worker/rest/api/v3/SinkApiV3ResourceTest.java
+++ b/pulsar-functions/worker/src/test/java/org/apache/pulsar/functions/worker/rest/api/v3/SinkApiV3ResourceTest.java
@@ -52,6 +52,7 @@
import org.apache.distributedlog.api.namespace.Namespace;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.config.Configurator;
+import org.apache.pulsar.broker.authentication.AuthenticationParameters;
import org.apache.pulsar.client.admin.Functions;
import org.apache.pulsar.client.admin.Namespaces;
import org.apache.pulsar.client.admin.Packages;
@@ -534,7 +535,7 @@ private void testRegisterSinkMissingArguments(
details,
pkgUrl,
sinkConfig,
- null, null);
+ null);
}
@@ -548,7 +549,7 @@ public void testMissingSinkConfig() {
mockedFormData,
null,
null,
- null, null);
+ null);
}
@Test(expectedExceptions = RestException.class, expectedExceptionsMessageRegExp = "Sink config is not provided")
@@ -562,7 +563,7 @@ public void testUpdateMissingSinkConfig() {
mockedFormData,
null,
null,
- null, null, null);
+ null, null);
}
private void registerDefaultSink() throws IOException {
@@ -580,7 +581,7 @@ private void registerDefaultSinkWithPackageUrl(String packageUrl) throws IOExcep
mockedFormData,
packageUrl,
sinkConfig,
- null, null);
+ null);
}
}
@@ -652,7 +653,7 @@ public void testRegisterSinkConflictingFields() throws Exception {
mockedFormData,
null,
sinkConfig,
- null, null);
+ null);
}
}
@@ -754,7 +755,7 @@ public void testRegisterSinkSuccessWithTransformFunction() throws Exception {
mockedFormData,
null,
sinkConfig,
- null, null);
+ null);
}
}
@@ -803,7 +804,7 @@ public void testRegisterSinkFailureWithInvalidTransformFunction() throws Excepti
mockedFormData,
null,
sinkConfig,
- null, null);
+ null);
}
} catch (RestException e) {
// expected exception
@@ -1021,7 +1022,7 @@ private void testUpdateSinkMissingArguments(
details,
null,
sinkConfig,
- null, null, null);
+ null, null);
}
@@ -1064,7 +1065,7 @@ private void updateDefaultSinkWithPackageUrl(String packageUrl) throws Exception
mockedFormData,
packageUrl,
sinkConfig,
- null, null, null);
+ null, null);
}
}
@@ -1149,7 +1150,7 @@ public void testUpdateSinkWithUrl() throws Exception {
null,
filePackageUrl,
sinkConfig,
- null, null, null);
+ null, null);
}
@Test(expectedExceptions = RestException.class, expectedExceptionsMessageRegExp = "sink failed to register")
@@ -1249,7 +1250,7 @@ public void testUpdateSinkDifferentTransformFunction() throws Exception {
mockedFormData,
null,
sinkConfig,
- null, null, null);
+ null, null);
}
}
@@ -1308,7 +1309,7 @@ private void testDeregisterSinkMissingArguments(
tenant,
namespace,
sink,
- null, null);
+ null);
}
@@ -1317,7 +1318,7 @@ private void deregisterDefaultSink() {
tenant,
namespace,
sink,
- null, null);
+ null);
}
@Test(expectedExceptions = RestException.class, expectedExceptionsMessageRegExp = "Sink test-sink doesn't exist")
@@ -1532,7 +1533,8 @@ private void testGetSinkMissingArguments(
resource.getFunctionInfo(
tenant,
namespace,
- sink, null, null
+ sink,
+ AuthenticationParameters.builder().build()
);
}
@@ -1541,7 +1543,8 @@ private SinkConfig getDefaultSinkInfo() {
return resource.getSinkInfo(
tenant,
namespace,
- sink
+ sink,
+ AuthenticationParameters.builder().build()
);
}
@@ -1634,7 +1637,8 @@ private void testListSinksMissingArguments(
) {
resource.listFunctions(
tenant,
- namespace, null, null
+ namespace,
+ AuthenticationParameters.builder().build()
);
}
@@ -1642,7 +1646,8 @@ private void testListSinksMissingArguments(
private List listDefaultSinks() {
return resource.listFunctions(
tenant,
- namespace, null, null
+ namespace,
+ AuthenticationParameters.builder().build()
);
}
@@ -1779,7 +1784,7 @@ public void testRegisterSinkSuccessK8sNoUpload() throws Exception {
mockedFormData,
null,
sinkConfig,
- null, null);
+ null);
}
}
@@ -1836,7 +1841,7 @@ public void testRegisterSinkSuccessK8sWithUpload() throws Exception {
mockedFormData,
null,
sinkConfig,
- null, null);
+ null);
Assert.fail();
} catch (RuntimeException e) {
Assert.assertEquals(e.getMessage(), injectedErrMsg);
diff --git a/pulsar-functions/worker/src/test/java/org/apache/pulsar/functions/worker/rest/api/v3/SourceApiV3ResourceTest.java b/pulsar-functions/worker/src/test/java/org/apache/pulsar/functions/worker/rest/api/v3/SourceApiV3ResourceTest.java
index 303fa559b1d8e..36be2de716661 100644
--- a/pulsar-functions/worker/src/test/java/org/apache/pulsar/functions/worker/rest/api/v3/SourceApiV3ResourceTest.java
+++ b/pulsar-functions/worker/src/test/java/org/apache/pulsar/functions/worker/rest/api/v3/SourceApiV3ResourceTest.java
@@ -51,6 +51,7 @@
import org.apache.distributedlog.api.namespace.Namespace;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.config.Configurator;
+import org.apache.pulsar.broker.authentication.AuthenticationParameters;
import org.apache.pulsar.client.admin.Functions;
import org.apache.pulsar.client.admin.Namespaces;
import org.apache.pulsar.client.admin.Packages;
@@ -488,7 +489,7 @@ private void testRegisterSourceMissingArguments(
details,
pkgUrl,
sourceConfig,
- null, null);
+ null);
}
@@ -502,7 +503,7 @@ public void testMissingSinkConfig() {
mockedFormData,
null,
null,
- null, null);
+ null);
}
@Test(expectedExceptions = RestException.class, expectedExceptionsMessageRegExp = "Source config is not provided")
@@ -516,7 +517,7 @@ public void testUpdateMissingSinkConfig() {
mockedFormData,
null,
null,
- null, null, null);
+ null, null);
}
private void registerDefaultSource() throws IOException {
@@ -533,7 +534,7 @@ private void registerDefaultSourceWithPackageUrl(String packageUrl) throws IOExc
null,
packageUrl,
sourceConfig,
- null, null);
+ null);
}
@Test(expectedExceptions = RestException.class, expectedExceptionsMessageRegExp = "Source test-source already "
@@ -634,7 +635,7 @@ public void testRegisterSourceConflictingFields() throws Exception {
mockedFormData,
null,
sourceConfig,
- null, null);
+ null);
}
}
@@ -937,7 +938,7 @@ private void testUpdateSourceMissingArguments(
details,
null,
sourceConfig,
- null, null, null);
+ null, null);
}
@@ -983,7 +984,7 @@ private void updateDefaultSourceWithPackageUrl(String packageUrl) throws Excepti
mockedFormData,
packageUrl,
sourceConfig,
- null, null, null);
+ null, null);
}
}
@@ -1069,7 +1070,7 @@ public void testUpdateSourceWithUrl() throws Exception {
null,
filePackageUrl,
sourceConfig,
- null, null, null);
+ null, null);
}
@@ -1182,7 +1183,7 @@ private void testDeregisterSourceMissingArguments(
tenant,
namespace,
function,
- null, null);
+ null);
}
@@ -1191,7 +1192,7 @@ private void deregisterDefaultSource() {
tenant,
namespace,
source,
- null, null);
+ null);
}
@Test(expectedExceptions = RestException.class, expectedExceptionsMessageRegExp = "Source test-source doesn't " +
@@ -1385,7 +1386,8 @@ private void testGetSourceMissingArguments(
resource.getFunctionInfo(
tenant,
namespace,
- source, null, null
+ source,
+ AuthenticationParameters.builder().build()
);
}
@@ -1393,7 +1395,8 @@ private SourceConfig getDefaultSourceInfo() {
return resource.getSourceInfo(
tenant,
namespace,
- source
+ source,
+ AuthenticationParameters.builder().build()
);
}
@@ -1476,14 +1479,17 @@ private void testListSourcesMissingArguments(
) {
resource.listFunctions(
tenant,
- namespace, null, null
+ namespace,
+ AuthenticationParameters.builder().build()
);
}
private List listDefaultSources() {
return resource.listFunctions(
tenant,
- namespace, null, null);
+ namespace,
+ AuthenticationParameters.builder().build()
+ );
}
@Test