/*
* 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.ranger.tagsync.source.atlasrest;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.security.SecureClientLogin;
import org.apache.ranger.plugin.util.RangerRESTClient;
import org.apache.ranger.tagsync.model.AbstractTagSource;
import org.apache.ranger.plugin.util.ServiceTags;
import org.apache.ranger.tagsync.model.TagSink;
import org.apache.ranger.tagsync.process.TagSyncConfig;
import org.apache.ranger.tagsync.process.TagSynchronizer;
import org.apache.ranger.tagsync.source.atlas.AtlasEntityWithTraits;
import org.apache.ranger.tagsync.source.atlas.AtlasNotificationMapper;
import org.apache.ranger.tagsync.source.atlas.AtlasResourceMapperUtil;
import java.util.List;
import java.util.Map;
import java.util.Properties;
public class AtlasRESTTagSource extends AbstractTagSource implements Runnable {
private static final Log LOG = LogFactory.getLog(AtlasRESTTagSource.class);
static final String AUTH_TYPE_KERBEROS = "kerberos";
private long sleepTimeBetweenCycleInMillis;
AtlasRESTUtil atlasRESTUtil = null;
private String authenticationType;
private String principal;
private String keytab;
private String nameRules;
private Thread myThread = null;
public static void main(String[] args) {
AtlasRESTTagSource atlasRESTTagSource = new AtlasRESTTagSource();
TagSyncConfig config = TagSyncConfig.getInstance();
Properties props = config.getProperties();
TagSynchronizer.printConfigurationProperties(props);
TagSink tagSink = TagSynchronizer.initializeTagSink(props);
if (tagSink != null) {
if (atlasRESTTagSource.initialize(props)) {
try {
tagSink.start();
atlasRESTTagSource.setTagSink(tagSink);
atlasRESTTagSource.synchUp();
} catch (Exception exception) {
LOG.error("ServiceTags upload failed : ", exception);
System.exit(1);
}
} else {
LOG.error("AtlasRESTTagSource initialized failed, exiting.");
System.exit(1);
}
} else {
LOG.error("TagSink initialialization failed, exiting.");
System.exit(1);
}
}
@Override
public boolean initialize(Properties properties) {
if (LOG.isDebugEnabled()) {
LOG.debug("==> AtlasRESTTagSource.initialize()");
}
boolean ret = AtlasResourceMapperUtil.initializeAtlasResourceMappers(properties);
sleepTimeBetweenCycleInMillis = TagSyncConfig.getTagSourceAtlasDownloadIntervalInMillis(properties);
String restUrl = TagSyncConfig.getAtlasRESTEndpoint(properties);
String sslConfigFile = TagSyncConfig.getAtlasRESTSslConfigFile(properties);
String userName = TagSyncConfig.getAtlasRESTUserName(properties);
String password = TagSyncConfig.getAtlasRESTPassword(properties);
authenticationType = TagSyncConfig.getAuthenticationType(properties);
nameRules = TagSyncConfig.getNameRules(properties);
principal = TagSyncConfig.getKerberosPrincipal(properties);
keytab = TagSyncConfig.getKerberosKeytab(properties);
final boolean kerberized = StringUtils.isNotEmpty(authenticationType)
&& authenticationType.trim().equalsIgnoreCase(AtlasRESTTagSource.AUTH_TYPE_KERBEROS)
&& SecureClientLogin.isKerberosCredentialExists(principal, keytab);
if (LOG.isDebugEnabled()) {
LOG.debug("restUrl=" + restUrl);
LOG.debug("sslConfigFile=" + sslConfigFile);
LOG.debug("userName=" + userName);
LOG.debug("authenticationType=" + authenticationType);
LOG.debug("principal=" + principal);
LOG.debug("keytab=" + keytab);
LOG.debug("nameRules=" + nameRules);
LOG.debug("kerberized=" + kerberized);
}
if (StringUtils.isNotEmpty(restUrl)) {
if (!restUrl.endsWith("/")) {
restUrl += "/";
}
RangerRESTClient atlasRESTClient = new RangerRESTClient(restUrl, sslConfigFile);
if (!kerberized) {
atlasRESTClient.setBasicAuthInfo(userName, password);
}
atlasRESTUtil = new AtlasRESTUtil(atlasRESTClient, kerberized, authenticationType, principal, keytab, nameRules);
} else {
LOG.info("AtlasEndpoint not specified, Initial download of Atlas-entities cannot be done.");
ret = false;
}
if (LOG.isDebugEnabled()) {
LOG.debug("<== AtlasRESTTagSource.initialize(), result=" + ret);
}
return ret;
}
@Override
public boolean start() {
myThread = new Thread(this);
myThread.setDaemon(true);
myThread.start();
return true;
}
@Override
public void stop() {
if (myThread != null && myThread.isAlive()) {
myThread.interrupt();
}
}
@Override
public void run() {
if (LOG.isDebugEnabled()) {
LOG.debug("==> AtlasRESTTagSource.run()");
}
while (true) {
synchUp();
LOG.debug("Sleeping for [" + sleepTimeBetweenCycleInMillis + "] milliSeconds");
try {
Thread.sleep(sleepTimeBetweenCycleInMillis);
} catch (InterruptedException exception) {
LOG.error("Interrupted..: ", exception);
return;
}
}
}
public void synchUp() {
List<AtlasEntityWithTraits> atlasEntities = atlasRESTUtil.getAtlasEntities();
if (CollectionUtils.isNotEmpty(atlasEntities)) {
if (LOG.isDebugEnabled()) {
for (AtlasEntityWithTraits element : atlasEntities) {
LOG.debug(element);
}
}
Map<String, ServiceTags> serviceTagsMap = AtlasNotificationMapper.processAtlasEntities(atlasEntities);
if (MapUtils.isNotEmpty(serviceTagsMap)) {
for (Map.Entry<String, ServiceTags> entry : serviceTagsMap.entrySet()) {
if (LOG.isDebugEnabled()) {
Gson gsonBuilder = new GsonBuilder().setDateFormat("yyyyMMdd-HH:mm:ss.SSS-Z")
.setPrettyPrinting()
.create();
String serviceTagsString = gsonBuilder.toJson(entry.getValue());
LOG.debug("serviceTags=" + serviceTagsString);
}
updateSink(entry.getValue());
}
}
}
}
}