/*
* Licensed 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 com.addthis.hydra.job.auth;
import javax.annotation.Nonnull;
import java.io.IOException;
import java.util.Objects;
import java.util.UUID;
import com.google.common.base.Splitter;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class AuthorizationManagerBasic extends AuthorizationManager {
private static final Logger log = LoggerFactory.getLogger(AuthorizationManagerBasic.class);
private static final Splitter COMMA_SPLITTER = Splitter.on(',').trimResults().omitEmptyStrings();
@Nonnull
private final TokenCache sudoCache;
@Nonnull
private final boolean groupModifyPermissions;
@JsonCreator
public AuthorizationManagerBasic(@JsonProperty("sudoCache") TokenCache sudoCache,
@JsonProperty("groupModifyPermissions") boolean groupModifyPermissions) {
this.sudoCache = sudoCache;
this.groupModifyPermissions = groupModifyPermissions;
log.info("Registering basic authorization");
}
@Override boolean isWritable(User user, String sudo, WritableAsset asset) {
if ((user == null) || (asset == null)) {
return false;
} else if (sudoCache.get(user.name(), sudo)) {
return true;
} else {
return isWritable(user, asset);
}
}
@Override boolean isExecutable(User user, String sudo, ExecutableAsset asset) {
if ((user == null) || (asset == null)) {
return false;
} else if (sudoCache.get(user.name(), sudo)) {
return true;
} else {
return isExecutable(user, asset);
}
}
@Override boolean canModifyPermissions(User user, String sudo, WritableAsset asset) {
String assetOwner = asset.getOwner();
String assetGroup = asset.getGroup();
if (Objects.equals(user.name(), assetOwner)) {
return true;
} else if (groupModifyPermissions && (assetGroup != null) && user.groups().contains(assetGroup)) {
return true;
} else {
return isWritable(user, sudo, asset);
}
}
@Override boolean adminAction(User user, String sudoToken) {
if ((user == null) || (sudoToken == null)) {
return false;
} else {
return sudoCache.get(user.name(), sudoToken);
}
}
private boolean isWritable(User user, WritableAsset asset) {
return testPermissions(user, asset, asset.isOwnerWritable(),
asset.isGroupWritable(), asset.isWorldWritable());
}
private boolean isExecutable(User user, ExecutableAsset asset) {
return testPermissions(user, asset, asset.isOwnerExecutable(),
asset.isGroupExecutable(), asset.isWorldExecutable());
}
private boolean testPermissions(User user, OwnableAsset asset, boolean owner, boolean group, boolean world) {
if (Objects.equals(user.name(), asset.getOwner())) {
return owner;
}
String assetGroup = asset.getGroup();
if (assetGroup != null) {
for (String component : COMMA_SPLITTER.split(assetGroup)) {
if (user.groups().contains(component)) {
return group;
}
}
}
return world;
}
@Override String sudo(User user, boolean admin) {
if (admin) {
UUID uuid = UUID.randomUUID();
String token = uuid.toString();
sudoCache.put(user.name(), token);
return token;
} else {
return null;
}
}
@Override void logout(String username) {
sudoCache.evict(username);
}
@Override
public void close() throws IOException {
sudoCache.close();
}
}