/** * In remote mode, we should not cache the explore request */ @Override protected boolean checkExploreAndDetermineCache(ImpersonationRequest impersonationRequest) throws IOException { return !(impersonationRequest.getEntityId().getEntityType().equals(EntityType.NAMESPACE) && impersonationRequest.getImpersonatedOpType().equals(ImpersonatedOpType.EXPLORE)); }
@Override public int hashCode() { return Objects.hash(request.getPrincipal()); } }
@Override public final UGIWithPrincipal getConfiguredUGI(ImpersonationRequest impersonationRequest) throws IOException { try { UGIWithPrincipal ugi = impersonationRequest.getImpersonatedOpType().equals(ImpersonatedOpType.EXPLORE) || impersonationRequest.getPrincipal() == null ? null : ugiCache.getIfPresent(new UGICacheKey(impersonationRequest)); if (ugi != null) { return ugi; } boolean isCache = checkExploreAndDetermineCache(impersonationRequest); ImpersonationInfo info = getPrincipalForEntity(impersonationRequest); ImpersonationRequest newRequest = new ImpersonationRequest(impersonationRequest.getEntityId(), impersonationRequest.getImpersonatedOpType(), info.getPrincipal(), info.getKeytabURI()); return isCache ? ugiCache.get(new UGICacheKey(newRequest)) : createUGI(newRequest); } catch (ExecutionException e) { Throwable cause = e.getCause(); // Propagate if the cause is an IOException or RuntimeException Throwables.propagateIfPossible(cause, IOException.class); // Otherwise always wrap it with IOException throw new IOException(cause); } }
ownerAdmin); ImpersonationRequest aliceImpRequest = new ImpersonationRequest(aliceEntity, ImpersonatedOpType.OTHER); UGIWithPrincipal aliceUGIWithPrincipal = ugiProvider.getConfiguredUGI(aliceImpRequest); Assert.assertArrayEquals(aliceImpRequest.getImpersonatedOpType().toString().getBytes(StandardCharsets.UTF_8), token.getIdentifier()); Assert.assertArrayEquals(aliceImpRequest.getImpersonatedOpType().toString().getBytes(StandardCharsets.UTF_8), token.getPassword()); Assert.assertEquals(new Text("opType"), token.getKind());
private UserGroupInformation getUGI(NamespacedEntityId entityId, ImpersonatedOpType impersonatedOpType) throws IOException { UserGroupInformation currentUser = UserGroupInformation.getCurrentUser(); // don't impersonate if kerberos isn't enabled OR if the operation is in the system namespace if (!kerberosEnabled || NamespaceId.SYSTEM.equals(entityId.getNamespaceId())) { return currentUser; } ImpersonationRequest impersonationRequest = new ImpersonationRequest(entityId, impersonatedOpType); // if the current user is not same as cdap master user then it means we are already impersonating some user // and hence we should not allow another impersonation. See CDAP-8641 and CDAP-13123 // Note that this is just a temporary fix and we will need to revisit the impersonation model in the future. if (!currentUser.getShortUserName().equals(masterShortUsername)) { LOG.debug("Not impersonating for {} as the call is already impersonated as {}", impersonationRequest, currentUser); IMPERSONATION_FAILTURE_LOG.warn("Not impersonating for {} as the call is already impersonated as {}", impersonationRequest, currentUser); return currentUser; } return ugiProvider.getConfiguredUGI(impersonationRequest).getUGI(); } }
private ImpersonationInfo getPrincipalForEntity(ImpersonationRequest request) throws IOException { ImpersonationInfo impersonationInfo = SecurityUtil.createImpersonationInfo(ownerAdmin, cConf, request.getEntityId()); LOG.debug("Obtained impersonation info: {} for entity {}", impersonationInfo, request.getEntityId()); return impersonationInfo; }
String configuredPrincipalShortName = new KerberosName(impersonationRequest.getPrincipal()).getShortName(); if (UserGroupInformation.getCurrentUser().getShortUserName().equals(configuredPrincipalShortName)) { return new UGIWithPrincipal(impersonationRequest.getPrincipal(), UserGroupInformation.getCurrentUser()); URI keytabURI = URI.create(impersonationRequest.getKeytabURI()); boolean isKeytabLocal = keytabURI.getScheme() == null || "file".equals(keytabURI.getScheme()); new File(keytabURI.getPath()) : localizeKeytab(locationFactory.create(keytabURI)); try { String expandedPrincipal = SecurityUtil.expandPrincipal(impersonationRequest.getPrincipal()); LOG.debug("Logging in as: principal={}, keytab={}", expandedPrincipal, localKeytabFile); return new UGIWithPrincipal(impersonationRequest.getPrincipal(), loggedInUGI); } finally { if (!isKeytabLocal && !localKeytabFile.delete()) {
@Override protected UGIWithPrincipal createUGI(ImpersonationRequest impersonationRequest) throws IOException { ImpersonationRequest jsonRequest = new ImpersonationRequest(impersonationRequest.getEntityId(), impersonationRequest.getImpersonatedOpType(), impersonationRequest.getPrincipal()); PrincipalCredentials principalCredentials = GSON.fromJson(executeRequest(jsonRequest).getResponseBodyAsString(), PrincipalCredentials.class); LOG.debug("Received response: {}", principalCredentials); Location location = locationFactory.create(URI.create(principalCredentials.getCredentialsPath())); try { String user = principalCredentials.getPrincipal(); if (impersonationRequest.getImpersonatedOpType() == ImpersonatedOpType.EXPLORE) { // For explore operations, we use the short name in UserGroupInformation, to avoid an incorrect // check in Hive. See CDAP-12930 user = new KerberosName(user).getShortName(); } UserGroupInformation impersonatedUGI = UserGroupInformation.createRemoteUser(user); impersonatedUGI.addCredentials(readCredentials(location)); return new UGIWithPrincipal(principalCredentials.getPrincipal(), impersonatedUGI); } finally { try { if (!location.delete()) { LOG.warn("Failed to delete location: {}", location); } } catch (IOException e) { LOG.warn("Exception raised when deleting location {}", location, e); } } }
@Test public void testDefaultUGIProviderWithHDFSFiles() throws Exception { // create a location on hdfs for keytabs Location hdfsKeytabDir = locationFactory.create("keytabs"); // set in the cConf so that later it can be used to fetch the keytabs for the given principal setKeytabDir(hdfsKeytabDir.toURI().toString()); Location aliceRemoteKeytabFile = copyFileToHDFS(hdfsKeytabDir, aliceKeytabFile); Location bobRemoteKeytabFile = copyFileToHDFS(hdfsKeytabDir, bobKeytabFile); OwnerAdmin ownerAdmin = getOwnerAdmin(); DefaultUGIProvider provider = new DefaultUGIProvider(cConf, locationFactory, ownerAdmin, namespaceClient); // add some entity owners ownerAdmin.add(aliceEntity, aliceKerberosPrincipalId); ownerAdmin.add(bobEntity, bobKerberosPrincipalId); // Try with keytab file on hdfs ImpersonationRequest aliceImpRequest = new ImpersonationRequest(aliceEntity, ImpersonatedOpType.OTHER); ImpersonationRequest bobImpRequest = new ImpersonationRequest(bobEntity, ImpersonatedOpType.OTHER); UGIWithPrincipal aliceUGIWithPrincipal = verifyAndGetUGI(provider, aliceKerberosPrincipalId, aliceImpRequest); UGIWithPrincipal bobUGIWithPrincipal = verifyAndGetUGI(provider, bobKerberosPrincipalId, bobImpRequest); // delete bob's keytab file on hdfs Assert.assertTrue(bobRemoteKeytabFile.delete()); // verify caching by ensuring that we are able to fetch bob's ugi even after delete but not after invalidating the // cache verifyCaching(provider, aliceImpRequest, bobImpRequest, aliceUGIWithPrincipal, bobUGIWithPrincipal); // cleanup ownerAdmin.delete(aliceEntity); ownerAdmin.delete(bobEntity); }
if (impersonationRequest.getEntityId().getEntityType().equals(EntityType.NAMESPACE) && impersonationRequest.getImpersonatedOpType().equals(ImpersonatedOpType.EXPLORE)) { namespaceQueryAdmin.get(impersonationRequest.getEntityId().getNamespaceId()).getConfig(); if (!nsConfig.isExploreAsPrincipal()) { throw new FeatureDisabledException(FeatureDisabledException.Feature.EXPLORE, NamespaceConfig.class.getSimpleName() + " of " + impersonationRequest.getEntityId(), NamespaceConfig.EXPLORE_AS_PRINCIPAL, String.valueOf(true));
ImpersonationRequest aliceImpRequest = new ImpersonationRequest(aliceEntity, ImpersonatedOpType.OTHER); ImpersonationRequest bobImpRequest = new ImpersonationRequest(bobEntity, ImpersonatedOpType.OTHER); UGIWithPrincipal aliceUGIWithPrincipal = verifyAndGetUGI(provider, aliceKerberosPrincipalId, aliceImpRequest); UGIWithPrincipal bobUGIWithPrincipal = verifyAndGetUGI(provider, bobKerberosPrincipalId, bobImpRequest);
@Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } UGICacheKey cachekey = (UGICacheKey) o; return Objects.equals(request.getPrincipal(), cachekey.getRequest().getPrincipal()); }
new Token<>(impersonationRequest.getEntityId().toString().getBytes(StandardCharsets.UTF_8), impersonationRequest.getEntityId().toString().getBytes(StandardCharsets.UTF_8), new Text("entity"), new Text("service"))); credentials.addToken(new Text("opType"), new Token<>(impersonationRequest.getImpersonatedOpType().toString() .getBytes(StandardCharsets.UTF_8), impersonationRequest.getImpersonatedOpType().toString() .getBytes(StandardCharsets.UTF_8), new Text("opType"),