Search in sources :

Example 1 with PlainFactory

use of org.apache.drill.exec.rpc.security.plain.PlainFactory in project drill by axbaretto.

the class UserServer method getHandshakeHandler.

@Override
protected ServerHandshakeHandler<UserToBitHandshake> getHandshakeHandler(final BitToUserConnection connection) {
    return new ServerHandshakeHandler<UserToBitHandshake>(RpcType.HANDSHAKE, UserToBitHandshake.PARSER) {

        @Override
        protected void consumeHandshake(ChannelHandlerContext ctx, UserToBitHandshake inbound) throws Exception {
            BitToUserHandshake handshakeResp = getHandshakeResponse(inbound);
            OutboundRpcMessage msg = new OutboundRpcMessage(RpcMode.RESPONSE, this.handshakeType, coordinationId, handshakeResp);
            ctx.writeAndFlush(msg);
            if (handshakeResp.getStatus() != HandshakeStatus.SUCCESS && handshakeResp.getStatus() != HandshakeStatus.AUTH_REQUIRED) {
                // If handling handshake results in an error, throw an exception to terminate the connection.
                throw new RpcException("Handshake request failed: " + handshakeResp.getErrorMessage());
            }
        }

        @Override
        public BitToUserHandshake getHandshakeResponse(UserToBitHandshake inbound) throws Exception {
            if (logger.isTraceEnabled()) {
                logger.trace("Handling handshake from user to bit. {}", serializeUserToBitHandshakeWithoutPassword(inbound));
            }
            // if timeout is unsupported or is set to false, disable timeout.
            if (!inbound.hasSupportTimeout() || !inbound.getSupportTimeout()) {
                connection.disableReadTimeout();
                logger.warn("Timeout Disabled as client doesn't support it.", connection.getName());
            }
            BitToUserHandshake.Builder respBuilder = BitToUserHandshake.newBuilder().setRpcVersion(UserRpcConfig.RPC_VERSION).setServerInfos(UserRpcUtils.getRpcEndpointInfos(SERVER_NAME)).addAllSupportedMethods(UserRpcConfig.SUPPORTED_SERVER_METHODS);
            try {
                if (inbound.getRpcVersion() != UserRpcConfig.RPC_VERSION) {
                    final String errMsg = String.format("Invalid rpc version. Expected %d, actual %d.", UserRpcConfig.RPC_VERSION, inbound.getRpcVersion());
                    return handleFailure(respBuilder, HandshakeStatus.RPC_VERSION_MISMATCH, errMsg, null);
                }
                connection.setHandshake(inbound);
                if (!config.isAuthEnabled()) {
                    connection.finalizeSession(inbound.getCredentials().getUserName());
                    respBuilder.setStatus(HandshakeStatus.SUCCESS);
                    return respBuilder.build();
                }
                // If sasl_support field is absent in handshake message then treat the client as < 1.10 client
                final boolean clientSupportsSasl = inbound.hasSaslSupport();
                // saslSupportOrdinal will be set to UNKNOWN_SASL_SUPPORT, if sasl_support field in handshake is set to a
                // value which is unknown to this server. We will treat those clients as one which knows SASL protocol.
                final int saslSupportOrdinal = (clientSupportsSasl) ? inbound.getSaslSupport().ordinal() : SaslSupport.UNKNOWN_SASL_SUPPORT.ordinal();
                // Check if client doesn't support SASL or only supports SASL_AUTH and server has encryption enabled
                if ((!clientSupportsSasl || saslSupportOrdinal == SaslSupport.SASL_AUTH.ordinal()) && config.isEncryptionEnabled()) {
                    throw new UserAuthenticationException("The server doesn't allow client without encryption support." + " Please upgrade your client or talk to your system administrator.");
                }
                if (!clientSupportsSasl) {
                    // for backward compatibility < 1.10
                    final String userName = inbound.getCredentials().getUserName();
                    if (logger.isTraceEnabled()) {
                        logger.trace("User {} on connection {} is likely using an older client.", userName, connection.getRemoteAddress());
                    }
                    try {
                        String password = "";
                        final UserProperties props = inbound.getProperties();
                        for (int i = 0; i < props.getPropertiesCount(); i++) {
                            Property prop = props.getProperties(i);
                            if (DrillProperties.PASSWORD.equalsIgnoreCase(prop.getKey())) {
                                password = prop.getValue();
                                break;
                            }
                        }
                        final PlainFactory plainFactory;
                        try {
                            plainFactory = (PlainFactory) config.getAuthProvider().getAuthenticatorFactory(PlainFactory.SIMPLE_NAME);
                        } catch (final SaslException e) {
                            throw new UserAuthenticationException("The server no longer supports username/password" + " based authentication. Please talk to your system administrator.");
                        }
                        plainFactory.getAuthenticator().authenticate(userName, password);
                        connection.changeHandlerTo(config.getMessageHandler());
                        connection.finalizeSession(userName);
                        respBuilder.setStatus(HandshakeStatus.SUCCESS);
                        if (logger.isTraceEnabled()) {
                            logger.trace("Authenticated {} successfully using PLAIN from {}", userName, connection.getRemoteAddress());
                        }
                        return respBuilder.build();
                    } catch (UserAuthenticationException ex) {
                        return handleFailure(respBuilder, HandshakeStatus.AUTH_FAILED, ex.getMessage(), ex);
                    }
                }
                // Offer all the configured mechanisms to client. If certain mechanism doesn't support encryption
                // like PLAIN, those should fail during the SASL handshake negotiation.
                respBuilder.addAllAuthenticationMechanisms(config.getAuthProvider().getAllFactoryNames());
                // set the encrypted flag in handshake message. For older clients this field is optional so will be ignored
                respBuilder.setEncrypted(connection.isEncryptionEnabled());
                respBuilder.setMaxWrappedSize(connection.getMaxWrappedSize());
                // for now, this means PLAIN credentials will be sent over twice
                // (during handshake and during sasl exchange)
                respBuilder.setStatus(HandshakeStatus.AUTH_REQUIRED);
                return respBuilder.build();
            } catch (Exception e) {
                return handleFailure(respBuilder, HandshakeStatus.UNKNOWN_FAILURE, e.getMessage(), e);
            }
        }
    };
}
Also used : PlainFactory(org.apache.drill.exec.rpc.security.plain.PlainFactory) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) SaslException(javax.security.sasl.SaslException) RpcException(org.apache.drill.exec.rpc.RpcException) SaslException(javax.security.sasl.SaslException) UserAuthenticationException(org.apache.drill.exec.rpc.user.security.UserAuthenticationException) DrillbitStartupException(org.apache.drill.exec.exception.DrillbitStartupException) IOException(java.io.IOException) DrillException(org.apache.drill.common.exceptions.DrillException) UserToBitHandshake(org.apache.drill.exec.proto.UserProtos.UserToBitHandshake) UserAuthenticationException(org.apache.drill.exec.rpc.user.security.UserAuthenticationException) UserProperties(org.apache.drill.exec.proto.UserProtos.UserProperties) BitToUserHandshake(org.apache.drill.exec.proto.UserProtos.BitToUserHandshake) OutboundRpcMessage(org.apache.drill.exec.rpc.OutboundRpcMessage) RpcException(org.apache.drill.exec.rpc.RpcException) Property(org.apache.drill.exec.proto.UserProtos.Property)

Example 2 with PlainFactory

use of org.apache.drill.exec.rpc.security.plain.PlainFactory in project drill by apache.

the class UserServer method getHandshakeHandler.

@Override
protected ServerHandshakeHandler<UserToBitHandshake> getHandshakeHandler(final BitToUserConnection connection) {
    return new ServerHandshakeHandler<UserToBitHandshake>(RpcType.HANDSHAKE, UserToBitHandshake.PARSER) {

        @Override
        protected void consumeHandshake(ChannelHandlerContext ctx, UserToBitHandshake inbound) throws Exception {
            BitToUserHandshake handshakeResp = getHandshakeResponse(inbound);
            OutboundRpcMessage msg = new OutboundRpcMessage(RpcMode.RESPONSE, this.handshakeType, coordinationId, handshakeResp);
            ctx.writeAndFlush(msg);
            if (handshakeResp.getStatus() != HandshakeStatus.SUCCESS && handshakeResp.getStatus() != HandshakeStatus.AUTH_REQUIRED) {
                // If handling handshake results in an error, throw an exception to terminate the connection.
                throw new RpcException("Handshake request failed: " + handshakeResp.getErrorMessage());
            }
        }

        @Override
        public BitToUserHandshake getHandshakeResponse(UserToBitHandshake inbound) throws Exception {
            if (logger.isTraceEnabled()) {
                logger.trace("Handling handshake from user to bit. {}", serializeUserToBitHandshakeWithoutPassword(inbound));
            }
            // if timeout is unsupported or is set to false, disable timeout.
            if (!inbound.hasSupportTimeout() || !inbound.getSupportTimeout()) {
                connection.disableReadTimeout();
                logger.warn("Timeout Disabled as client {} doesn't support it.", connection.getName());
            }
            BitToUserHandshake.Builder respBuilder = BitToUserHandshake.newBuilder().setRpcVersion(UserRpcConfig.RPC_VERSION).setServerInfos(UserRpcUtils.getRpcEndpointInfos(SERVER_NAME)).addAllSupportedMethods(UserRpcConfig.SUPPORTED_SERVER_METHODS);
            try {
                if (inbound.getRpcVersion() != UserRpcConfig.RPC_VERSION) {
                    final String errMsg = String.format("Invalid rpc version. Expected %d, actual %d.", UserRpcConfig.RPC_VERSION, inbound.getRpcVersion());
                    return handleFailure(respBuilder, HandshakeStatus.RPC_VERSION_MISMATCH, errMsg, null);
                }
                connection.setHandshake(inbound);
                if (!config.isAuthEnabled()) {
                    connection.finalizeSession(inbound.getCredentials().getUserName());
                    respBuilder.setStatus(HandshakeStatus.SUCCESS);
                    return respBuilder.build();
                }
                // If sasl_support field is absent in handshake message then treat the client as < 1.10 client
                final boolean clientSupportsSasl = inbound.hasSaslSupport();
                // saslSupportOrdinal will be set to UNKNOWN_SASL_SUPPORT, if sasl_support field in handshake is set to a
                // value which is unknown to this server. We will treat those clients as one which knows SASL protocol.
                final int saslSupportOrdinal = (clientSupportsSasl) ? inbound.getSaslSupport().ordinal() : SaslSupport.UNKNOWN_SASL_SUPPORT.ordinal();
                // Check if client doesn't support SASL or only supports SASL_AUTH and server has encryption enabled
                if ((!clientSupportsSasl || saslSupportOrdinal == SaslSupport.SASL_AUTH.ordinal()) && config.isEncryptionEnabled()) {
                    throw new UserAuthenticationException("The server doesn't allow client without encryption support." + " Please upgrade your client or talk to your system administrator.");
                }
                if (!clientSupportsSasl) {
                    // for backward compatibility < 1.10
                    final String userName = inbound.getCredentials().getUserName();
                    if (logger.isTraceEnabled()) {
                        logger.trace("User {} on connection {} is likely using an older client.", userName, connection.getRemoteAddress());
                    }
                    try {
                        String password = "";
                        final UserProperties props = inbound.getProperties();
                        for (int i = 0; i < props.getPropertiesCount(); i++) {
                            Property prop = props.getProperties(i);
                            if (DrillProperties.PASSWORD.equalsIgnoreCase(prop.getKey())) {
                                password = prop.getValue();
                                break;
                            }
                        }
                        final PlainFactory plainFactory;
                        try {
                            plainFactory = (PlainFactory) config.getAuthProvider().getAuthenticatorFactory(PlainFactory.SIMPLE_NAME);
                        } catch (final SaslException e) {
                            throw new UserAuthenticationException("The server no longer supports username/password" + " based authentication. Please talk to your system administrator.");
                        }
                        plainFactory.getAuthenticator().authenticate(userName, password);
                        connection.changeHandlerTo(config.getMessageHandler());
                        connection.finalizeSession(userName);
                        respBuilder.setStatus(HandshakeStatus.SUCCESS);
                        logger.info("Authenticated {} from {} successfully using PLAIN", userName, connection.getRemoteAddress());
                        return respBuilder.build();
                    } catch (UserAuthenticationException ex) {
                        return handleFailure(respBuilder, HandshakeStatus.AUTH_FAILED, ex.getMessage(), ex);
                    }
                }
                // Offer all the configured mechanisms to client. If certain mechanism doesn't support encryption
                // like PLAIN, those should fail during the SASL handshake negotiation.
                respBuilder.addAllAuthenticationMechanisms(config.getAuthProvider().getAllFactoryNames());
                // set the encrypted flag in handshake message. For older clients this field is optional so will be ignored
                respBuilder.setEncrypted(connection.isEncryptionEnabled());
                respBuilder.setMaxWrappedSize(connection.getMaxWrappedSize());
                // for now, this means PLAIN credentials will be sent over twice
                // (during handshake and during sasl exchange)
                respBuilder.setStatus(HandshakeStatus.AUTH_REQUIRED);
                return respBuilder.build();
            } catch (Exception e) {
                return handleFailure(respBuilder, HandshakeStatus.UNKNOWN_FAILURE, e.getMessage(), e);
            }
        }
    };
}
Also used : PlainFactory(org.apache.drill.exec.rpc.security.plain.PlainFactory) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) SaslException(javax.security.sasl.SaslException) RpcException(org.apache.drill.exec.rpc.RpcException) SaslException(javax.security.sasl.SaslException) UserAuthenticationException(org.apache.drill.exec.rpc.user.security.UserAuthenticationException) DrillbitStartupException(org.apache.drill.exec.exception.DrillbitStartupException) IOException(java.io.IOException) DrillException(org.apache.drill.common.exceptions.DrillException) UserToBitHandshake(org.apache.drill.exec.proto.UserProtos.UserToBitHandshake) UserAuthenticationException(org.apache.drill.exec.rpc.user.security.UserAuthenticationException) UserProperties(org.apache.drill.exec.proto.UserProtos.UserProperties) BitToUserHandshake(org.apache.drill.exec.proto.UserProtos.BitToUserHandshake) OutboundRpcMessage(org.apache.drill.exec.rpc.OutboundRpcMessage) RpcException(org.apache.drill.exec.rpc.RpcException) Property(org.apache.drill.exec.proto.UserProtos.Property)

Example 3 with PlainFactory

use of org.apache.drill.exec.rpc.security.plain.PlainFactory in project drill by apache.

the class DrillRestLoginService method login.

@Override
public UserIdentity login(String username, Object credentials) {
    if (!(credentials instanceof String)) {
        return null;
    }
    try {
        // Authenticate WebUser locally using UserAuthenticator. If WebServer is started that guarantees the PLAIN
        // mechanism is configured and authenticator is also available
        final AuthenticatorFactory plainFactory = drillbitContext.getAuthProvider().getAuthenticatorFactory(PlainFactory.SIMPLE_NAME);
        final UserAuthenticator userAuthenticator = ((PlainFactory) plainFactory).getAuthenticator();
        // Authenticate the user with configured Authenticator
        userAuthenticator.authenticate(username, credentials.toString());
        logger.debug("WebUser {} is successfully authenticated", username);
        final SystemOptionManager sysOptions = drillbitContext.getOptionManager();
        final boolean isAdmin = ImpersonationUtil.hasAdminPrivileges(username, sysOptions.getOption(ExecConstants.ADMIN_USERS_KEY).string_val, sysOptions.getOption(ExecConstants.ADMIN_USER_GROUPS_KEY).string_val);
        // Create the UserPrincipal corresponding to logged in user.
        final Principal userPrincipal = new DrillUserPrincipal(username, isAdmin);
        final Subject subject = new Subject();
        subject.getPrincipals().add(userPrincipal);
        subject.getPrivateCredentials().add(credentials);
        if (isAdmin) {
            subject.getPrincipals().addAll(DrillUserPrincipal.ADMIN_PRINCIPALS);
            return identityService.newUserIdentity(subject, userPrincipal, DrillUserPrincipal.ADMIN_USER_ROLES);
        } else {
            subject.getPrincipals().addAll(DrillUserPrincipal.NON_ADMIN_PRINCIPALS);
            return identityService.newUserIdentity(subject, userPrincipal, DrillUserPrincipal.NON_ADMIN_USER_ROLES);
        }
    } catch (final Exception e) {
        if (e instanceof UserAuthenticationException) {
            logger.debug("Authentication failed for WebUser '{}'", username, e);
        } else {
            logger.error("UnExpected failure occurred for WebUser {} during login.", username, e);
        }
        return null;
    }
}
Also used : UserAuthenticationException(org.apache.drill.exec.rpc.user.security.UserAuthenticationException) SystemOptionManager(org.apache.drill.exec.server.options.SystemOptionManager) UserAuthenticator(org.apache.drill.exec.rpc.user.security.UserAuthenticator) PlainFactory(org.apache.drill.exec.rpc.security.plain.PlainFactory) AuthenticatorFactory(org.apache.drill.exec.rpc.security.AuthenticatorFactory) Principal(java.security.Principal) Subject(javax.security.auth.Subject) UserAuthenticationException(org.apache.drill.exec.rpc.user.security.UserAuthenticationException)

Example 4 with PlainFactory

use of org.apache.drill.exec.rpc.security.plain.PlainFactory in project drill by axbaretto.

the class DrillRestLoginService method login.

@Override
public UserIdentity login(String username, Object credentials) {
    if (!(credentials instanceof String)) {
        return null;
    }
    try {
        // Authenticate WebUser locally using UserAuthenticator. If WebServer is started that guarantees the PLAIN
        // mechanism is configured and authenticator is also available
        final AuthenticatorFactory plainFactory = drillbitContext.getAuthProvider().getAuthenticatorFactory(PlainFactory.SIMPLE_NAME);
        final UserAuthenticator userAuthenticator = ((PlainFactory) plainFactory).getAuthenticator();
        // Authenticate the user with configured Authenticator
        userAuthenticator.authenticate(username, credentials.toString());
        logger.debug("WebUser {} is successfully authenticated", username);
        final SystemOptionManager sysOptions = drillbitContext.getOptionManager();
        final boolean isAdmin = ImpersonationUtil.hasAdminPrivileges(username, ExecConstants.ADMIN_USERS_VALIDATOR.getAdminUsers(sysOptions), ExecConstants.ADMIN_USER_GROUPS_VALIDATOR.getAdminUserGroups(sysOptions));
        // Create the UserPrincipal corresponding to logged in user.
        final Principal userPrincipal = new DrillUserPrincipal(username, isAdmin);
        final Subject subject = new Subject();
        subject.getPrincipals().add(userPrincipal);
        subject.getPrivateCredentials().add(credentials);
        if (isAdmin) {
            subject.getPrincipals().addAll(DrillUserPrincipal.ADMIN_PRINCIPALS);
            return identityService.newUserIdentity(subject, userPrincipal, DrillUserPrincipal.ADMIN_USER_ROLES);
        } else {
            subject.getPrincipals().addAll(DrillUserPrincipal.NON_ADMIN_PRINCIPALS);
            return identityService.newUserIdentity(subject, userPrincipal, DrillUserPrincipal.NON_ADMIN_USER_ROLES);
        }
    } catch (final Exception e) {
        if (e instanceof UserAuthenticationException) {
            logger.debug("Authentication failed for WebUser '{}'", username, e);
        } else {
            logger.error("UnExpected failure occurred for WebUser {} during login.", username, e);
        }
        return null;
    }
}
Also used : UserAuthenticationException(org.apache.drill.exec.rpc.user.security.UserAuthenticationException) SystemOptionManager(org.apache.drill.exec.server.options.SystemOptionManager) UserAuthenticator(org.apache.drill.exec.rpc.user.security.UserAuthenticator) PlainFactory(org.apache.drill.exec.rpc.security.plain.PlainFactory) AuthenticatorFactory(org.apache.drill.exec.rpc.security.AuthenticatorFactory) Principal(java.security.Principal) Subject(javax.security.auth.Subject) UserAuthenticationException(org.apache.drill.exec.rpc.user.security.UserAuthenticationException)

Example 5 with PlainFactory

use of org.apache.drill.exec.rpc.security.plain.PlainFactory in project drill by apache.

the class DrillRestLoginService method login.

@Override
public UserIdentity login(String username, Object credentials, ServletRequest request) {
    if (!(credentials instanceof String)) {
        return null;
    }
    try {
        // Authenticate WebUser locally using UserAuthenticator. If WebServer is started that guarantees the PLAIN
        // mechanism is configured and authenticator is also available
        final AuthenticatorFactory plainFactory = drillbitContext.getAuthProvider().getAuthenticatorFactory(PlainFactory.SIMPLE_NAME);
        final UserAuthenticator userAuthenticator = ((PlainFactory) plainFactory).getAuthenticator();
        // Authenticate the user with configured Authenticator
        userAuthenticator.authenticate(username, credentials.toString());
        logger.info("WebUser {} logged in from {}:{}", username, request.getRemoteHost(), request.getRemotePort());
        final SystemOptionManager sysOptions = drillbitContext.getOptionManager();
        final boolean isAdmin = ImpersonationUtil.hasAdminPrivileges(username, ExecConstants.ADMIN_USERS_VALIDATOR.getAdminUsers(sysOptions), ExecConstants.ADMIN_USER_GROUPS_VALIDATOR.getAdminUserGroups(sysOptions));
        // Create the UserPrincipal corresponding to logged in user.
        final Principal userPrincipal = new DrillUserPrincipal(username, isAdmin);
        final Subject subject = new Subject();
        subject.getPrincipals().add(userPrincipal);
        subject.getPrivateCredentials().add(credentials);
        if (isAdmin) {
            subject.getPrincipals().addAll(DrillUserPrincipal.ADMIN_PRINCIPALS);
            return identityService.newUserIdentity(subject, userPrincipal, DrillUserPrincipal.ADMIN_USER_ROLES);
        } else {
            subject.getPrincipals().addAll(DrillUserPrincipal.NON_ADMIN_PRINCIPALS);
            return identityService.newUserIdentity(subject, userPrincipal, DrillUserPrincipal.NON_ADMIN_USER_ROLES);
        }
    } catch (final Exception e) {
        if (e instanceof UserAuthenticationException) {
            logger.debug("Authentication failed for WebUser '{}'", username, e);
        } else {
            logger.error("Unexpected failure occurred for WebUser {} during login.", username, e);
        }
        return null;
    }
}
Also used : UserAuthenticationException(org.apache.drill.exec.rpc.user.security.UserAuthenticationException) SystemOptionManager(org.apache.drill.exec.server.options.SystemOptionManager) UserAuthenticator(org.apache.drill.exec.rpc.user.security.UserAuthenticator) PlainFactory(org.apache.drill.exec.rpc.security.plain.PlainFactory) AuthenticatorFactory(org.apache.drill.exec.rpc.security.AuthenticatorFactory) Principal(java.security.Principal) Subject(javax.security.auth.Subject) UserAuthenticationException(org.apache.drill.exec.rpc.user.security.UserAuthenticationException)

Aggregations

PlainFactory (org.apache.drill.exec.rpc.security.plain.PlainFactory)5 UserAuthenticationException (org.apache.drill.exec.rpc.user.security.UserAuthenticationException)5 Principal (java.security.Principal)3 Subject (javax.security.auth.Subject)3 AuthenticatorFactory (org.apache.drill.exec.rpc.security.AuthenticatorFactory)3 UserAuthenticator (org.apache.drill.exec.rpc.user.security.UserAuthenticator)3 SystemOptionManager (org.apache.drill.exec.server.options.SystemOptionManager)3 ChannelHandlerContext (io.netty.channel.ChannelHandlerContext)2 IOException (java.io.IOException)2 SaslException (javax.security.sasl.SaslException)2 DrillException (org.apache.drill.common.exceptions.DrillException)2 DrillbitStartupException (org.apache.drill.exec.exception.DrillbitStartupException)2 BitToUserHandshake (org.apache.drill.exec.proto.UserProtos.BitToUserHandshake)2 Property (org.apache.drill.exec.proto.UserProtos.Property)2 UserProperties (org.apache.drill.exec.proto.UserProtos.UserProperties)2 UserToBitHandshake (org.apache.drill.exec.proto.UserProtos.UserToBitHandshake)2 OutboundRpcMessage (org.apache.drill.exec.rpc.OutboundRpcMessage)2 RpcException (org.apache.drill.exec.rpc.RpcException)2