Search in sources :

Example 6 with KerberosName

use of org.apache.hadoop.security.authentication.util.KerberosName in project cdap by caskdata.

the class ScheduleTaskRunner method execute.

/**
   * Executes a program without blocking until its completion.
   *
   * @return a {@link ListenableFuture} object that completes when the program completes
   */
public ListenableFuture<?> execute(final ProgramId id, Map<String, String> sysArgs, Map<String, String> userArgs) throws Exception {
    ProgramRuntimeService.RuntimeInfo runtimeInfo;
    String originalUserId = SecurityRequestContext.getUserId();
    try {
        // if the program has a namespace user configured then set that user in the security request context.
        // See: CDAP-7396
        String nsPrincipal = namespaceQueryAdmin.get(id.getNamespaceId()).getConfig().getPrincipal();
        if (nsPrincipal != null && SecurityUtil.isKerberosEnabled(cConf)) {
            SecurityRequestContext.setUserId(new KerberosName(nsPrincipal).getServiceName());
        }
        runtimeInfo = lifecycleService.start(id, sysArgs, userArgs, false);
    } catch (ProgramNotFoundException | ApplicationNotFoundException e) {
        throw new TaskExecutionException(String.format(UserMessages.getMessage(UserErrors.PROGRAM_NOT_FOUND), id), e, false);
    } finally {
        SecurityRequestContext.setUserId(originalUserId);
    }
    final ProgramController controller = runtimeInfo.getController();
    final CountDownLatch latch = new CountDownLatch(1);
    controller.addListener(new AbstractListener() {

        @Override
        public void init(ProgramController.State state, @Nullable Throwable cause) {
            if (state == ProgramController.State.COMPLETED) {
                completed();
            }
            if (state == ProgramController.State.ERROR) {
                error(controller.getFailureCause());
            }
        }

        @Override
        public void killed() {
            latch.countDown();
        }

        @Override
        public void completed() {
            latch.countDown();
        }

        @Override
        public void error(Throwable cause) {
            latch.countDown();
        }
    }, Threads.SAME_THREAD_EXECUTOR);
    return executorService.submit(new Callable<Void>() {

        @Override
        public Void call() throws Exception {
            latch.await();
            return null;
        }
    });
}
Also used : ProgramController(co.cask.cdap.app.runtime.ProgramController) KerberosName(org.apache.hadoop.security.authentication.util.KerberosName) CountDownLatch(java.util.concurrent.CountDownLatch) ProgramNotFoundException(co.cask.cdap.common.ProgramNotFoundException) ApplicationNotFoundException(co.cask.cdap.common.ApplicationNotFoundException) ApplicationNotFoundException(co.cask.cdap.common.ApplicationNotFoundException) AbstractListener(co.cask.cdap.internal.app.runtime.AbstractListener) ProgramNotFoundException(co.cask.cdap.common.ProgramNotFoundException) ProgramRuntimeService(co.cask.cdap.app.runtime.ProgramRuntimeService)

Example 7 with KerberosName

use of org.apache.hadoop.security.authentication.util.KerberosName in project cdap by caskdata.

the class DefaultNamespaceAdmin method create.

/**
   * Creates a new namespace
   *
   * @param metadata the {@link NamespaceMeta} for the new namespace to be created
   * @throws NamespaceAlreadyExistsException if the specified namespace already exists
   */
@Override
@AuthEnforce(entities = "instanceId", enforceOn = InstanceId.class, actions = Action.ADMIN)
public synchronized void create(final NamespaceMeta metadata) throws Exception {
    // TODO: CDAP-1427 - This should be transactional, but we don't support transactions on files yet
    Preconditions.checkArgument(metadata != null, "Namespace metadata should not be null.");
    NamespaceId namespace = metadata.getNamespaceId();
    if (exists(namespace)) {
        throw new NamespaceAlreadyExistsException(namespace);
    }
    // If this namespace has custom mapping then validate the given custom mapping
    if (hasCustomMapping(metadata)) {
        validateCustomMapping(metadata);
    }
    // check that the user has configured either both of none of the following configuration: principal and keytab URI
    boolean hasValidKerberosConf = false;
    if (metadata.getConfig() != null) {
        String configuredPrincipal = metadata.getConfig().getPrincipal();
        String configuredKeytabURI = metadata.getConfig().getKeytabURI();
        if ((!Strings.isNullOrEmpty(configuredPrincipal) && Strings.isNullOrEmpty(configuredKeytabURI)) || (Strings.isNullOrEmpty(configuredPrincipal) && !Strings.isNullOrEmpty(configuredKeytabURI))) {
            throw new BadRequestException(String.format("Either neither or both of the following two configurations must be configured. " + "Configured principal: %s, Configured keytabURI: %s", configuredPrincipal, configuredKeytabURI));
        }
        hasValidKerberosConf = true;
    }
    // check that if explore as principal is explicitly set to false then user has kerberos configuration
    if (!metadata.getConfig().isExploreAsPrincipal() && !hasValidKerberosConf) {
        throw new BadRequestException(String.format("No kerberos principal or keytab-uri was provided while '%s' was set to true.", NamespaceConfig.EXPLORE_AS_PRINCIPAL));
    }
    // Namespace can be created. Grant all the permissions to the user.
    Principal principal = authenticationContext.getPrincipal();
    privilegesManager.grant(namespace, principal, EnumSet.allOf(Action.class));
    // Also grant the user who will execute programs in this namespace all privileges on the namespace
    String executionUserName;
    if (SecurityUtil.isKerberosEnabled(cConf) && !NamespaceId.SYSTEM.equals(namespace)) {
        String namespacePrincipal = metadata.getConfig().getPrincipal();
        if (Strings.isNullOrEmpty(namespacePrincipal)) {
            executionUserName = new KerberosName(SecurityUtil.getMasterPrincipal(cConf)).getShortName();
        } else {
            executionUserName = new KerberosName(namespacePrincipal).getShortName();
        }
    } else {
        executionUserName = UserGroupInformation.getCurrentUser().getShortUserName();
    }
    Principal executionUser = new Principal(executionUserName, Principal.PrincipalType.USER);
    privilegesManager.grant(namespace, executionUser, EnumSet.allOf(Action.class));
    // store the meta first in the namespace store because namespacedLocationFactory needs to look up location
    // mapping from namespace config
    nsStore.create(metadata);
    try {
        UserGroupInformation ugi;
        if (NamespaceId.DEFAULT.equals(namespace)) {
            ugi = UserGroupInformation.getCurrentUser();
        } else {
            ugi = impersonator.getUGI(namespace);
        }
        ImpersonationUtils.doAs(ugi, new Callable<Void>() {

            @Override
            public Void call() throws Exception {
                storageProviderNamespaceAdmin.get().create(metadata);
                return null;
            }
        });
    } catch (Throwable t) {
        // failed to create namespace in underlying storage so delete the namespace meta stored in the store earlier
        deleteNamespaceMeta(metadata.getNamespaceId());
        privilegesManager.revoke(namespace);
        throw new NamespaceCannotBeCreatedException(namespace, t);
    }
    LOG.info("Namespace {} created with meta {}", metadata.getNamespaceId(), metadata);
}
Also used : Action(co.cask.cdap.proto.security.Action) NamespaceCannotBeCreatedException(co.cask.cdap.common.NamespaceCannotBeCreatedException) KerberosName(org.apache.hadoop.security.authentication.util.KerberosName) NamespaceCannotBeCreatedException(co.cask.cdap.common.NamespaceCannotBeCreatedException) NamespaceNotFoundException(co.cask.cdap.common.NamespaceNotFoundException) BadRequestException(co.cask.cdap.common.BadRequestException) UnauthorizedException(co.cask.cdap.security.spi.authorization.UnauthorizedException) NamespaceCannotBeDeletedException(co.cask.cdap.common.NamespaceCannotBeDeletedException) DatasetManagementException(co.cask.cdap.api.dataset.DatasetManagementException) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) NamespaceAlreadyExistsException(co.cask.cdap.common.NamespaceAlreadyExistsException) BadRequestException(co.cask.cdap.common.BadRequestException) NamespaceId(co.cask.cdap.proto.id.NamespaceId) NamespaceAlreadyExistsException(co.cask.cdap.common.NamespaceAlreadyExistsException) Principal(co.cask.cdap.proto.security.Principal) UserGroupInformation(org.apache.hadoop.security.UserGroupInformation) AuthEnforce(co.cask.cdap.common.security.AuthEnforce)

Example 8 with KerberosName

use of org.apache.hadoop.security.authentication.util.KerberosName in project hadoop by apache.

the class SaslRpcClient method getServerPrincipal.

/**
   * Get the remote server's principal.  The value will be obtained from
   * the config and cross-checked against the server's advertised principal.
   * 
   * @param authType of the SASL client
   * @return String of the server's principal
   * @throws IOException - error determining configured principal
   */
@VisibleForTesting
String getServerPrincipal(SaslAuth authType) throws IOException {
    KerberosInfo krbInfo = SecurityUtil.getKerberosInfo(protocol, conf);
    LOG.debug("Get kerberos info proto:" + protocol + " info:" + krbInfo);
    if (krbInfo == null) {
        // protocol has no support for kerberos
        return null;
    }
    String serverKey = krbInfo.serverPrincipal();
    if (serverKey == null) {
        throw new IllegalArgumentException("Can't obtain server Kerberos config key from protocol=" + protocol.getCanonicalName());
    }
    // construct server advertised principal for comparision
    String serverPrincipal = new KerberosPrincipal(authType.getProtocol() + "/" + authType.getServerId(), KerberosPrincipal.KRB_NT_SRV_HST).getName();
    // use the pattern if defined
    String serverKeyPattern = conf.get(serverKey + ".pattern");
    if (serverKeyPattern != null && !serverKeyPattern.isEmpty()) {
        Pattern pattern = GlobPattern.compile(serverKeyPattern);
        if (!pattern.matcher(serverPrincipal).matches()) {
            throw new IllegalArgumentException(String.format("Server has invalid Kerberos principal: %s," + " doesn't match the pattern: %s", serverPrincipal, serverKeyPattern));
        }
    } else {
        // check that the server advertised principal matches our conf
        String confPrincipal = SecurityUtil.getServerPrincipal(conf.get(serverKey), serverAddr.getAddress());
        if (LOG.isDebugEnabled()) {
            LOG.debug("getting serverKey: " + serverKey + " conf value: " + conf.get(serverKey) + " principal: " + confPrincipal);
        }
        if (confPrincipal == null || confPrincipal.isEmpty()) {
            throw new IllegalArgumentException("Failed to specify server's Kerberos principal name");
        }
        KerberosName name = new KerberosName(confPrincipal);
        if (name.getHostName() == null) {
            throw new IllegalArgumentException("Kerberos principal name does NOT have the expected hostname part: " + confPrincipal);
        }
        if (!serverPrincipal.equals(confPrincipal)) {
            throw new IllegalArgumentException(String.format("Server has invalid Kerberos principal: %s, expecting: %s", serverPrincipal, confPrincipal));
        }
    }
    return serverPrincipal;
}
Also used : KerberosPrincipal(javax.security.auth.kerberos.KerberosPrincipal) Pattern(com.google.re2j.Pattern) GlobPattern(org.apache.hadoop.fs.GlobPattern) ByteString(com.google.protobuf.ByteString) KerberosName(org.apache.hadoop.security.authentication.util.KerberosName) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Example 9 with KerberosName

use of org.apache.hadoop.security.authentication.util.KerberosName in project hadoop by apache.

the class KerberosAuthenticationHandler method init.

/**
   * Initializes the authentication handler instance.
   * <p>
   * It creates a Kerberos context using the principal and keytab specified in
   * the configuration.
   * <p>
   * This method is invoked by the {@link AuthenticationFilter#init} method.
   *
   * @param config configuration properties to initialize the handler.
   *
   * @throws ServletException thrown if the handler could not be initialized.
   */
@Override
public void init(Properties config) throws ServletException {
    try {
        String principal = config.getProperty(PRINCIPAL);
        if (principal == null || principal.trim().length() == 0) {
            throw new ServletException("Principal not defined in configuration");
        }
        keytab = config.getProperty(KEYTAB, keytab);
        if (keytab == null || keytab.trim().length() == 0) {
            throw new ServletException("Keytab not defined in configuration");
        }
        if (!new File(keytab).exists()) {
            throw new ServletException("Keytab does not exist: " + keytab);
        }
        // use all SPNEGO principals in the keytab if a principal isn't
        // specifically configured
        final String[] spnegoPrincipals;
        if (principal.equals("*")) {
            spnegoPrincipals = KerberosUtil.getPrincipalNames(keytab, Pattern.compile("HTTP/.*"));
            if (spnegoPrincipals.length == 0) {
                throw new ServletException("Principals do not exist in the keytab");
            }
        } else {
            spnegoPrincipals = new String[] { principal };
        }
        String nameRules = config.getProperty(NAME_RULES, null);
        if (nameRules != null) {
            KerberosName.setRules(nameRules);
        }
        for (String spnegoPrincipal : spnegoPrincipals) {
            LOG.info("Login using keytab {}, for principal {}", keytab, spnegoPrincipal);
            final KerberosConfiguration kerberosConfiguration = new KerberosConfiguration(keytab, spnegoPrincipal);
            final LoginContext loginContext = new LoginContext("", serverSubject, null, kerberosConfiguration);
            try {
                loginContext.login();
            } catch (LoginException le) {
                LOG.warn("Failed to login as [{}]", spnegoPrincipal, le);
                throw new AuthenticationException(le);
            }
            loginContexts.add(loginContext);
            KerberosName kerbName = new KerberosName(spnegoPrincipal);
            if (kerbName.getHostName() != null && kerbName.getServiceName() != null && kerbName.getServiceName().equals("HTTP")) {
                boolean added = serverPrincipalMap.put(kerbName.getHostName(), spnegoPrincipal);
                LOG.info("Map server: {} to principal: [{}], added = {}", kerbName.getHostName(), spnegoPrincipal, added);
            } else {
                LOG.warn("HTTP principal: [{}] is invalid for SPNEGO!", spnegoPrincipal);
            }
        }
        try {
            gssManager = Subject.doAs(serverSubject, new PrivilegedExceptionAction<GSSManager>() {

                @Override
                public GSSManager run() throws Exception {
                    return GSSManager.getInstance();
                }
            });
        } catch (PrivilegedActionException ex) {
            throw ex.getException();
        }
    } catch (Exception ex) {
        throw new ServletException(ex);
    }
}
Also used : AuthenticationException(org.apache.hadoop.security.authentication.client.AuthenticationException) PrivilegedActionException(java.security.PrivilegedActionException) KerberosName(org.apache.hadoop.security.authentication.util.KerberosName) PrivilegedExceptionAction(java.security.PrivilegedExceptionAction) LoginException(javax.security.auth.login.LoginException) AuthenticationException(org.apache.hadoop.security.authentication.client.AuthenticationException) ServletException(javax.servlet.ServletException) PrivilegedActionException(java.security.PrivilegedActionException) IOException(java.io.IOException) GSSException(org.ietf.jgss.GSSException) ServletException(javax.servlet.ServletException) LoginContext(javax.security.auth.login.LoginContext) LoginException(javax.security.auth.login.LoginException) File(java.io.File)

Example 10 with KerberosName

use of org.apache.hadoop.security.authentication.util.KerberosName in project hadoop by apache.

the class KerberosAuthenticationHandler method runWithPrincipal.

private AuthenticationToken runWithPrincipal(String serverPrincipal, byte[] clientToken, Base64 base64, HttpServletResponse response) throws IOException, AuthenticationException, ClassNotFoundException, GSSException, IllegalAccessException, NoSuchFieldException {
    GSSContext gssContext = null;
    GSSCredential gssCreds = null;
    AuthenticationToken token = null;
    try {
        LOG.trace("SPNEGO initiated with server principal [{}]", serverPrincipal);
        gssCreds = this.gssManager.createCredential(this.gssManager.createName(serverPrincipal, KerberosUtil.getOidInstance("NT_GSS_KRB5_PRINCIPAL")), GSSCredential.INDEFINITE_LIFETIME, new Oid[] { KerberosUtil.getOidInstance("GSS_SPNEGO_MECH_OID"), KerberosUtil.getOidInstance("GSS_KRB5_MECH_OID") }, GSSCredential.ACCEPT_ONLY);
        gssContext = this.gssManager.createContext(gssCreds);
        byte[] serverToken = gssContext.acceptSecContext(clientToken, 0, clientToken.length);
        if (serverToken != null && serverToken.length > 0) {
            String authenticate = base64.encodeToString(serverToken);
            response.setHeader(KerberosAuthenticator.WWW_AUTHENTICATE, KerberosAuthenticator.NEGOTIATE + " " + authenticate);
        }
        if (!gssContext.isEstablished()) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            LOG.trace("SPNEGO in progress");
        } else {
            String clientPrincipal = gssContext.getSrcName().toString();
            KerberosName kerberosName = new KerberosName(clientPrincipal);
            String userName = kerberosName.getShortName();
            token = new AuthenticationToken(userName, clientPrincipal, getType());
            response.setStatus(HttpServletResponse.SC_OK);
            LOG.trace("SPNEGO completed for client principal [{}]", clientPrincipal);
        }
    } finally {
        if (gssContext != null) {
            gssContext.dispose();
        }
        if (gssCreds != null) {
            gssCreds.dispose();
        }
    }
    return token;
}
Also used : GSSCredential(org.ietf.jgss.GSSCredential) GSSContext(org.ietf.jgss.GSSContext) Oid(org.ietf.jgss.Oid) KerberosName(org.apache.hadoop.security.authentication.util.KerberosName)

Aggregations

KerberosName (org.apache.hadoop.security.authentication.util.KerberosName)10 IOException (java.io.IOException)5 File (java.io.File)2 ServletException (javax.servlet.ServletException)2 UserGroupInformation (org.apache.hadoop.security.UserGroupInformation)2 AuthenticationException (org.apache.hadoop.security.authentication.client.AuthenticationException)2 DatasetManagementException (co.cask.cdap.api.dataset.DatasetManagementException)1 ProgramController (co.cask.cdap.app.runtime.ProgramController)1 ProgramRuntimeService (co.cask.cdap.app.runtime.ProgramRuntimeService)1 ApplicationNotFoundException (co.cask.cdap.common.ApplicationNotFoundException)1 BadRequestException (co.cask.cdap.common.BadRequestException)1 FeatureDisabledException (co.cask.cdap.common.FeatureDisabledException)1 NamespaceAlreadyExistsException (co.cask.cdap.common.NamespaceAlreadyExistsException)1 NamespaceCannotBeCreatedException (co.cask.cdap.common.NamespaceCannotBeCreatedException)1 NamespaceCannotBeDeletedException (co.cask.cdap.common.NamespaceCannotBeDeletedException)1 NamespaceNotFoundException (co.cask.cdap.common.NamespaceNotFoundException)1 ProgramNotFoundException (co.cask.cdap.common.ProgramNotFoundException)1 AuthEnforce (co.cask.cdap.common.security.AuthEnforce)1 AbstractListener (co.cask.cdap.internal.app.runtime.AbstractListener)1 NamespaceConfig (co.cask.cdap.proto.NamespaceConfig)1