org.apache.hadoop.yarn.server.timeline.security.TimelineACLsManager.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.hadoop.yarn.server.timeline.security.TimelineACLsManager.java

Source

/**
 * 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.hadoop.yarn.server.timeline.security;

import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.collections.map.LRUMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.classification.InterfaceAudience.Private;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.security.authorize.AccessControlList;
import org.apache.hadoop.yarn.api.records.ApplicationAccessType;
import org.apache.hadoop.yarn.api.records.timeline.TimelineDomain;
import org.apache.hadoop.yarn.api.records.timeline.TimelineEntity;
import org.apache.hadoop.yarn.conf.YarnConfiguration;
import org.apache.hadoop.yarn.exceptions.YarnException;
import org.apache.hadoop.yarn.security.AdminACLsManager;
import org.apache.hadoop.yarn.server.timeline.EntityIdentifier;
import org.apache.hadoop.yarn.server.timeline.TimelineStore;
import org.apache.hadoop.yarn.util.StringHelper;

import com.google.common.annotations.VisibleForTesting;

/**
 * <code>TimelineACLsManager</code> check the entity level timeline data access.
 */
@Private
public class TimelineACLsManager {

    private static final Log LOG = LogFactory.getLog(TimelineACLsManager.class);
    private static final int DOMAIN_ACCESS_ENTRY_CACHE_SIZE = 100;

    private AdminACLsManager adminAclsManager;
    private Map<String, AccessControlListExt> aclExts;
    private TimelineStore store;

    @SuppressWarnings("unchecked")
    public TimelineACLsManager(Configuration conf) {
        this.adminAclsManager = new AdminACLsManager(conf);
        aclExts = Collections.synchronizedMap(new LRUMap(DOMAIN_ACCESS_ENTRY_CACHE_SIZE));
    }

    public void setTimelineStore(TimelineStore store) {
        this.store = store;
    }

    private AccessControlListExt loadDomainFromTimelineStore(String domainId) throws IOException {
        if (store == null) {
            return null;
        }
        TimelineDomain domain = store.getDomain(domainId);
        if (domain == null) {
            return null;
        } else {
            return putDomainIntoCache(domain);
        }
    }

    public void replaceIfExist(TimelineDomain domain) {
        if (aclExts.containsKey(domain.getId())) {
            putDomainIntoCache(domain);
        }
    }

    private AccessControlListExt putDomainIntoCache(TimelineDomain domain) {
        Map<ApplicationAccessType, AccessControlList> acls = new HashMap<ApplicationAccessType, AccessControlList>(
                2);
        acls.put(ApplicationAccessType.VIEW_APP, new AccessControlList(StringHelper.cjoin(domain.getReaders())));
        acls.put(ApplicationAccessType.MODIFY_APP, new AccessControlList(StringHelper.cjoin(domain.getWriters())));
        AccessControlListExt aclExt = new AccessControlListExt(domain.getOwner(), acls);
        aclExts.put(domain.getId(), aclExt);
        return aclExt;
    }

    public boolean checkAccess(UserGroupInformation callerUGI, ApplicationAccessType applicationAccessType,
            TimelineEntity entity) throws YarnException, IOException {
        if (LOG.isDebugEnabled()) {
            LOG.debug("Verifying the access of " + (callerUGI == null ? null : callerUGI.getShortUserName())
                    + " on the timeline entity "
                    + new EntityIdentifier(entity.getEntityId(), entity.getEntityType()));
        }

        if (!adminAclsManager.areACLsEnabled()) {
            return true;
        }

        // find domain owner and acls
        AccessControlListExt aclExt = aclExts.get(entity.getDomainId());
        if (aclExt == null) {
            aclExt = loadDomainFromTimelineStore(entity.getDomainId());
        }
        if (aclExt == null) {
            throw new YarnException("Domain information of the timeline entity "
                    + new EntityIdentifier(entity.getEntityId(), entity.getEntityType()) + " doesn't exist.");
        }
        String owner = aclExt.owner;
        AccessControlList domainACL = aclExt.acls.get(applicationAccessType);
        if (domainACL == null) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("ACL not found for access-type " + applicationAccessType + " for domain "
                        + entity.getDomainId() + " owned by " + owner + ". Using default ["
                        + YarnConfiguration.DEFAULT_YARN_APP_ACL + "]");
            }
            domainACL = new AccessControlList(YarnConfiguration.DEFAULT_YARN_APP_ACL);
        }

        if (callerUGI != null && (adminAclsManager.isAdmin(callerUGI) || callerUGI.getShortUserName().equals(owner)
                || domainACL.isUserAllowed(callerUGI))) {
            return true;
        }
        return false;
    }

    public boolean checkAccess(UserGroupInformation callerUGI, TimelineDomain domain)
            throws YarnException, IOException {
        if (LOG.isDebugEnabled()) {
            LOG.debug("Verifying the access of " + (callerUGI == null ? null : callerUGI.getShortUserName())
                    + " on the timeline domain " + domain);
        }

        if (!adminAclsManager.areACLsEnabled()) {
            return true;
        }

        String owner = domain.getOwner();
        if (owner == null || owner.length() == 0) {
            throw new YarnException(
                    "Owner information of the timeline domain " + domain.getId() + " is corrupted.");
        }
        if (callerUGI != null
                && (adminAclsManager.isAdmin(callerUGI) || callerUGI.getShortUserName().equals(owner))) {
            return true;
        }
        return false;
    }

    @Private
    @VisibleForTesting
    public AdminACLsManager setAdminACLsManager(AdminACLsManager adminAclsManager) {
        AdminACLsManager oldAdminACLsManager = this.adminAclsManager;
        this.adminAclsManager = adminAclsManager;
        return oldAdminACLsManager;
    }

    private static class AccessControlListExt {
        private String owner;
        private Map<ApplicationAccessType, AccessControlList> acls;

        public AccessControlListExt(String owner, Map<ApplicationAccessType, AccessControlList> acls) {
            this.owner = owner;
            this.acls = acls;
        }
    }
}