Search in sources :

Example 16 with AuthData

use of org.apache.pulsar.common.api.AuthData in project incubator-pulsar by apache.

the class ServerCnx method handleAuthResponse.

@Override
protected void handleAuthResponse(CommandAuthResponse authResponse) {
    checkArgument(authResponse.hasResponse());
    checkArgument(authResponse.getResponse().hasAuthData() && authResponse.getResponse().hasAuthMethodName());
    pendingAuthChallengeResponse = false;
    if (log.isDebugEnabled()) {
        log.debug("Received AuthResponse from {}, auth method: {}", remoteAddress, authResponse.getResponse().getAuthMethodName());
    }
    try {
        AuthData clientData = AuthData.of(authResponse.getResponse().getAuthData());
        doAuthentication(clientData, authResponse.getProtocolVersion(), authResponse.getClientVersion());
    } catch (AuthenticationException e) {
        service.getPulsarStats().recordConnectionCreateFail();
        log.warn("[{}] Authentication failed: {} ", remoteAddress, e.getMessage());
        ctx.writeAndFlush(Commands.newError(-1, ServerError.AuthenticationError, e.getMessage()));
        close();
    } catch (Exception e) {
        service.getPulsarStats().recordConnectionCreateFail();
        String msg = "Unable to handleAuthResponse";
        log.warn("[{}] {} ", remoteAddress, msg, e);
        ctx.writeAndFlush(Commands.newError(-1, ServerError.UnknownError, msg));
        close();
    }
}
Also used : AuthData(org.apache.pulsar.common.api.AuthData) AuthenticationException(javax.naming.AuthenticationException) ServiceUnitNotReadyException(org.apache.pulsar.broker.service.BrokerServiceException.ServiceUnitNotReadyException) RestException(org.apache.pulsar.broker.web.RestException) InterceptException(org.apache.pulsar.common.intercept.InterceptException) TopicNotFoundException(org.apache.pulsar.broker.service.BrokerServiceException.TopicNotFoundException) ServerMetadataException(org.apache.pulsar.broker.service.BrokerServiceException.ServerMetadataException) AuthenticationException(javax.naming.AuthenticationException) PulsarClientException(org.apache.pulsar.client.api.PulsarClientException) SubscriptionNotFoundException(org.apache.pulsar.broker.service.BrokerServiceException.SubscriptionNotFoundException) ManagedLedgerException(org.apache.bookkeeper.mledger.ManagedLedgerException) IncompatibleSchemaException(org.apache.pulsar.broker.service.schema.exceptions.IncompatibleSchemaException) CoordinatorException(org.apache.pulsar.transaction.coordinator.exceptions.CoordinatorException) NoSuchElementException(java.util.NoSuchElementException) ConsumerBusyException(org.apache.pulsar.broker.service.BrokerServiceException.ConsumerBusyException)

Example 17 with AuthData

use of org.apache.pulsar.common.api.AuthData in project incubator-pulsar by apache.

the class ServerCnx method doAuthentication.

// According to auth result, send newConnected or newAuthChallenge command.
private State doAuthentication(AuthData clientData, int clientProtocolVersion, String clientVersion) throws Exception {
    // The original auth state can only be set on subsequent auth attempts (and only
    // in presence of a proxy and if the proxy is forwarding the credentials).
    // In this case, the re-validation needs to be done against the original client
    // credentials.
    boolean useOriginalAuthState = (originalAuthState != null);
    AuthenticationState authState = useOriginalAuthState ? originalAuthState : this.authState;
    String authRole = useOriginalAuthState ? originalPrincipal : this.authRole;
    AuthData brokerData = authState.authenticate(clientData);
    if (log.isDebugEnabled()) {
        log.debug("Authenticate using original auth state : {}, role = {}", useOriginalAuthState, authRole);
    }
    if (authState.isComplete()) {
        // Authentication has completed. It was either:
        // 1. the 1st time the authentication process was done, in which case we'll send
        // a `CommandConnected` response
        // 2. an authentication refresh, in which case we need to refresh authenticationData
        String newAuthRole = authState.getAuthRole();
        // Refresh the auth data.
        this.authenticationData = authState.getAuthDataSource();
        if (log.isDebugEnabled()) {
            log.debug("[{}] Auth data refreshed for role={}", remoteAddress, this.authRole);
        }
        if (!useOriginalAuthState) {
            this.authRole = newAuthRole;
        }
        if (log.isDebugEnabled()) {
            log.debug("[{}] Client successfully authenticated with {} role {} and originalPrincipal {}", remoteAddress, authMethod, this.authRole, originalPrincipal);
        }
        if (state != State.Connected) {
            // First time authentication is done
            completeConnect(clientProtocolVersion, clientVersion);
        } else {
            // If the connection was already ready, it means we're doing a refresh
            if (!StringUtils.isEmpty(authRole)) {
                if (!authRole.equals(newAuthRole)) {
                    log.warn("[{}] Principal cannot change during an authentication refresh expected={} got={}", remoteAddress, authRole, newAuthRole);
                    ctx.close();
                } else {
                    log.info("[{}] Refreshed authentication credentials for role {}", remoteAddress, authRole);
                }
            }
        }
        return State.Connected;
    }
    // auth not complete, continue auth with client side.
    ctx.writeAndFlush(Commands.newAuthChallenge(authMethod, brokerData, clientProtocolVersion));
    if (log.isDebugEnabled()) {
        log.debug("[{}] Authentication in progress client by method {}.", remoteAddress, authMethod);
        log.debug("[{}] connect state change to : [{}]", remoteAddress, State.Connecting.name());
    }
    return State.Connecting;
}
Also used : AuthData(org.apache.pulsar.common.api.AuthData) AuthenticationState(org.apache.pulsar.broker.authentication.AuthenticationState)

Example 18 with AuthData

use of org.apache.pulsar.common.api.AuthData in project incubator-pulsar by apache.

the class ServerCnx method refreshAuthenticationCredentials.

public void refreshAuthenticationCredentials() {
    AuthenticationState authState = this.originalAuthState != null ? originalAuthState : this.authState;
    if (authState == null) {
        // Authentication is disabled or there's no local state to refresh
        return;
    } else if (getState() != State.Connected || !isActive) {
        // Connection is either still being established or already closed.
        return;
    } else if (!authState.isExpired()) {
        // Credentials are still valid. Nothing to do at this point
        return;
    } else if (originalPrincipal != null && originalAuthState == null) {
        log.info("[{}] Cannot revalidate user credential when using proxy and" + " not forwarding the credentials. Closing connection", remoteAddress);
        return;
    }
    ctx.executor().execute(SafeRun.safeRun(() -> {
        log.info("[{}] Refreshing authentication credentials for originalPrincipal {} and authRole {}", remoteAddress, originalPrincipal, this.authRole);
        if (!supportsAuthenticationRefresh()) {
            log.warn("[{}] Closing connection because client doesn't support auth credentials refresh", remoteAddress);
            ctx.close();
            return;
        }
        if (pendingAuthChallengeResponse) {
            log.warn("[{}] Closing connection after timeout on refreshing auth credentials", remoteAddress);
            ctx.close();
            return;
        }
        try {
            AuthData brokerData = authState.refreshAuthentication();
            ctx.writeAndFlush(Commands.newAuthChallenge(authMethod, brokerData, getRemoteEndpointProtocolVersion()));
            if (log.isDebugEnabled()) {
                log.debug("[{}] Sent auth challenge to client to refresh credentials with method: {}.", remoteAddress, authMethod);
            }
            pendingAuthChallengeResponse = true;
        } catch (AuthenticationException e) {
            log.warn("[{}] Failed to refresh authentication: {}", remoteAddress, e);
            ctx.close();
        }
    }));
}
Also used : AuthData(org.apache.pulsar.common.api.AuthData) AuthenticationException(javax.naming.AuthenticationException) AuthenticationState(org.apache.pulsar.broker.authentication.AuthenticationState)

Example 19 with AuthData

use of org.apache.pulsar.common.api.AuthData in project incubator-pulsar by apache.

the class ProxyConnection method handleConnect.

@Override
protected void handleConnect(CommandConnect connect) {
    checkArgument(state == State.Init);
    this.setRemoteEndpointProtocolVersion(connect.getProtocolVersion());
    this.hasProxyToBrokerUrl = connect.hasProxyToBrokerUrl();
    this.protocolVersionToAdvertise = getProtocolVersionToAdvertise(connect);
    this.proxyToBrokerUrl = connect.hasProxyToBrokerUrl() ? connect.getProxyToBrokerUrl() : "null";
    if (LOG.isDebugEnabled()) {
        LOG.debug("Received CONNECT from {} proxyToBroker={}", remoteAddress, proxyToBrokerUrl);
        LOG.debug("[{}] Protocol version to advertise to broker is {}, clientProtocolVersion={}, proxyProtocolVersion={}", remoteAddress, protocolVersionToAdvertise, getRemoteEndpointProtocolVersion(), Commands.getCurrentProtocolVersion());
    }
    if (getRemoteEndpointProtocolVersion() < ProtocolVersion.v10.getValue()) {
        LOG.warn("[{}] Client doesn't support connecting through proxy", remoteAddress);
        state = State.Closing;
        ctx.close();
        return;
    }
    try {
        // init authn
        this.clientConf = createClientConfiguration();
        // authn not enabled, complete
        if (!service.getConfiguration().isAuthenticationEnabled()) {
            completeConnect(null);
            return;
        }
        AuthData clientData = AuthData.of(connect.hasAuthData() ? connect.getAuthData() : EMPTY_CREDENTIALS);
        if (connect.hasAuthMethodName()) {
            authMethod = connect.getAuthMethodName();
        } else if (connect.hasAuthMethod()) {
            // Legacy client is passing enum
            authMethod = connect.getAuthMethod().name().substring(10).toLowerCase();
        } else {
            authMethod = "none";
        }
        authenticationProvider = service.getAuthenticationService().getAuthenticationProvider(authMethod);
        // In AuthenticationDisabled, it will set authMethod "none".
        if (authenticationProvider == null) {
            clientAuthRole = service.getAuthenticationService().getAnonymousUserRole().orElseThrow(() -> new AuthenticationException("No anonymous role, and no authentication provider configured"));
            completeConnect(clientData);
            return;
        }
        // init authState and other var
        ChannelHandler sslHandler = ctx.channel().pipeline().get(PulsarChannelInitializer.TLS_HANDLER);
        SSLSession sslSession = null;
        if (sslHandler != null) {
            sslSession = ((SslHandler) sslHandler).engine().getSession();
        }
        authState = authenticationProvider.newAuthState(clientData, remoteAddress, sslSession);
        authenticationData = authState.getAuthDataSource();
        doAuthentication(clientData);
    } catch (Exception e) {
        LOG.warn("[{}] Unable to authenticate: ", remoteAddress, e);
        ctx.writeAndFlush(Commands.newError(-1, ServerError.AuthenticationError, "Failed to authenticate")).addListener(ChannelFutureListener.CLOSE);
    }
}
Also used : AuthData(org.apache.pulsar.common.api.AuthData) AuthenticationException(javax.naming.AuthenticationException) SSLSession(javax.net.ssl.SSLSession) ChannelHandler(io.netty.channel.ChannelHandler) SslHandler(io.netty.handler.ssl.SslHandler) AuthenticationException(javax.naming.AuthenticationException) PulsarClientException(org.apache.pulsar.client.api.PulsarClientException) RejectedExecutionException(java.util.concurrent.RejectedExecutionException) PulsarServerException(org.apache.pulsar.broker.PulsarServerException)

Example 20 with AuthData

use of org.apache.pulsar.common.api.AuthData in project incubator-pulsar by apache.

the class SaslAuthenticateTest method testSaslServerAndClientAuth.

// Test sasl server/client auth.
@Test
public void testSaslServerAndClientAuth() throws Exception {
    log.info("-- {} -- start", methodName);
    String hostName = "localhost";
    // prepare client and server side resource
    AuthenticationDataProvider dataProvider = authSasl.getAuthData(hostName);
    AuthenticationProviderList providerList = (AuthenticationProviderList) (pulsar.getBrokerService().getAuthenticationService().getAuthenticationProvider(SaslConstants.AUTH_METHOD_NAME));
    AuthenticationProviderSasl saslServer = (AuthenticationProviderSasl) providerList.getProviders().get(0);
    AuthenticationState authState = saslServer.newAuthState(null, null, null);
    // auth between server and client.
    // first time auth
    AuthData initData1 = dataProvider.authenticate(AuthData.INIT_AUTH_DATA);
    AuthData serverData1 = authState.authenticate(initData1);
    boolean complete = authState.isComplete();
    assertFalse(complete);
    // second time auth, completed
    AuthData initData2 = dataProvider.authenticate(serverData1);
    AuthData serverData2 = authState.authenticate(initData2);
    complete = authState.isComplete();
    assertTrue(complete);
    assertNull(serverData2.getBytes());
    // if completed, server could not auth again.
    try {
        authState.authenticate(initData2);
        fail("Expected fail because auth completed for authState");
    } catch (Exception e) {
    // expected
    }
    // another server could not serve old client
    try {
        AuthenticationState authState2 = saslServer.newAuthState(null, null, null);
        AuthData serverData3 = authState2.authenticate(initData1);
        fail("Expected fail. server is auth old client data");
    } catch (Exception e) {
    // expected
    }
    log.info("-- {} -- end", methodName);
}
Also used : AuthenticationDataProvider(org.apache.pulsar.client.api.AuthenticationDataProvider) AuthData(org.apache.pulsar.common.api.AuthData) Test(org.testng.annotations.Test)

Aggregations

AuthData (org.apache.pulsar.common.api.AuthData)49 AuthenticationException (javax.naming.AuthenticationException)17 PulsarClientException (org.apache.pulsar.client.api.PulsarClientException)17 AuthenticationState (org.apache.pulsar.broker.authentication.AuthenticationState)11 Test (org.testng.annotations.Test)9 AuthenticationProvider (org.apache.pulsar.broker.authentication.AuthenticationProvider)8 ByteBuf (io.netty.buffer.ByteBuf)6 ChannelHandler (io.netty.channel.ChannelHandler)6 SslHandler (io.netty.handler.ssl.SslHandler)6 NoSuchElementException (java.util.NoSuchElementException)6 SSLSession (javax.net.ssl.SSLSession)6 ManagedLedgerException (org.apache.bookkeeper.mledger.ManagedLedgerException)6 PulsarServerException (org.apache.pulsar.broker.PulsarServerException)6 ConsumerBusyException (org.apache.pulsar.broker.service.BrokerServiceException.ConsumerBusyException)6 ServerMetadataException (org.apache.pulsar.broker.service.BrokerServiceException.ServerMetadataException)6 ServiceUnitNotReadyException (org.apache.pulsar.broker.service.BrokerServiceException.ServiceUnitNotReadyException)6 SubscriptionNotFoundException (org.apache.pulsar.broker.service.BrokerServiceException.SubscriptionNotFoundException)6 TopicNotFoundException (org.apache.pulsar.broker.service.BrokerServiceException.TopicNotFoundException)6 IncompatibleSchemaException (org.apache.pulsar.broker.service.schema.exceptions.IncompatibleSchemaException)6 RestException (org.apache.pulsar.broker.web.RestException)6