/*
* dCache - http://www.dcache.org/
*
* Copyright (C) 2016 Deutsches Elektronen-Synchrotron
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package diskCacheV111.doors;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import diskCacheV111.util.CheckStagePermission;
import dmg.cells.nucleus.CellAddressCore;
import dmg.cells.nucleus.CellEndpoint;
import dmg.cells.nucleus.CellPath;
import org.dcache.auth.CachingLoginStrategy;
import org.dcache.auth.LoginStrategy;
import org.dcache.auth.UnionLoginStrategy;
import org.dcache.auth.attributes.Restriction;
import org.dcache.auth.attributes.Restrictions;
import org.dcache.cells.CellStub;
import org.dcache.poolmanager.PoolManagerHandler;
import org.dcache.poolmanager.PoolManagerStub;
import org.dcache.services.login.RemoteLoginStrategy;
import org.dcache.util.Option;
import static diskCacheV111.doors.DCapDoorInterpreterV3._log;
public class DcapDoorSettings
{
@Option(name = "authorization")
protected String auth;
@Option(name = "anonymous-access")
protected String anon;
@Option(name = "poolManager",
description = "Cell address of the pool manager",
defaultValue = "PoolManager")
protected CellPath poolManager;
@Option(name = "pnfsManager",
description = "Cell address of the PNFS manager",
defaultValue = "PnfsManager")
protected CellPath pnfsManager;
@Option(name = "pinManager",
description = "Cell address of the pin manager",
defaultValue = "PinManager")
protected CellPath pinManager;
@Option(name = "gplazma",
description = "Cell address of GPlazma",
defaultValue = "gplazma")
protected CellPath gPlazma;
@Option(name = "billing",
description = "Cell address of billing",
defaultValue = "billing")
protected CellPath billing;
@Option(name = "hsm",
description = "Cell address of hsm manager",
defaultValue = "hsm")
protected CellPath hsmManager;
@Option(name = "truncate")
protected boolean isTruncateAllowed;
@Option(name = "allow-access-policy-overwrite")
protected boolean isAccessLatencyOverwriteAllowed;
@Option(name = "allow-retention-policy-overwrite")
protected boolean isRetentionPolicyOverwriteAllowed;
@Option(name = "check", defaultValue = "true")
protected boolean isCheckStrict;
// A string with the following format:
// majorMin.minorMin[.bugfixMin[-packageMin]][:majorMax.minorMax[.bugfix[-packageMax]]
@Option(name = "clientVersion")
protected String clientVersion;
@Option(name = "poolRetry", defaultValue = "0")
protected long poolRetry;
@Option(name = "io-queue")
protected String ioQueueName;
@Option(name = "io-queue-overwrite")
protected boolean ioQueueAllowOverwrite;
@Option(name = "read-only")
protected boolean isReadOnly;
@Option(name = "stageConfigurationFilePath")
protected String stageConfigurationFilePath;
/**
* If true, then the Subject of the request must have a UID and
* GID. If false, then a Subject without a UID and GID (i.e. a
* Nobody) will be allowed to proceed, but only allowed to perform
* operations authorized to world.
*/
private boolean isAuthorizationStrong;
/**
* If false, then authorization checks on read and write
* operations are bypassed for non URL operations. If true, then
* such operations are subject to authorization checks.
*/
private boolean isAuthorizationRequired;
private UnionLoginStrategy.AccessLevel anonymousAccessLevel;
private DCapDoorInterpreterV3.Version minClientVersion = new DCapDoorInterpreterV3.Version(0, 0);
private DCapDoorInterpreterV3.Version maxClientVersion = new DCapDoorInterpreterV3.Version(Integer.MAX_VALUE, Integer.MAX_VALUE);
private Restriction doorRestriction;
private CheckStagePermission checkStagePermission;
public void init()
{
isAuthorizationStrong = (auth != null) && auth.equals("strong");
isAuthorizationRequired = (auth != null) && (auth.equals("strong") || auth.equals("required"));
anonymousAccessLevel = (anon != null)
? UnionLoginStrategy.AccessLevel.valueOf(anon.toUpperCase())
: UnionLoginStrategy.AccessLevel.READONLY;
if (clientVersion != null) {
try {
List<String> values = Splitter.on(':').limit(2).trimResults().splitToList(clientVersion);
if (values.get(0).isEmpty()) {
throw new IllegalArgumentException("missing minimum version");
}
minClientVersion = new DCapDoorInterpreterV3.Version(values.get(0));
if (values.size() > 1) {
if (values.get(1).isEmpty()) {
throw new IllegalArgumentException("missing maximum version");
}
maxClientVersion = new DCapDoorInterpreterV3.Version(values.get(1));
}
} catch (IllegalArgumentException e) {
_log.error("Ignoring client version limits: syntax error with '{}': {}", clientVersion, e.getMessage());
}
}
ioQueueName = Strings.emptyToNull(ioQueueName);
doorRestriction = isReadOnly ? Restrictions.readOnly() : Restrictions.none();
checkStagePermission = new CheckStagePermission(stageConfigurationFilePath);
}
public boolean isAuthorizationRequired()
{
return isAuthorizationRequired;
}
public CellPath getPnfsManager()
{
return pnfsManager;
}
public CellPath getPoolManager()
{
return poolManager;
}
public CellPath getPinManager()
{
return pinManager;
}
public CellPath getGplazma()
{
return gPlazma;
}
public CellPath getBilling()
{
return billing;
}
public CellPath getHsmManager()
{
return hsmManager;
}
public boolean isTruncateAllowed()
{
return isTruncateAllowed;
}
public boolean isAccessLatencyOverwriteAllowed()
{
return isAccessLatencyOverwriteAllowed;
}
public boolean isRetentionPolicyOverwriteAllowed()
{
return isRetentionPolicyOverwriteAllowed;
}
public boolean isCheckStrict()
{
return isCheckStrict;
}
public DCapDoorInterpreterV3.Version getMinClientVersion()
{
return minClientVersion;
}
public DCapDoorInterpreterV3.Version getMaxClientVersion()
{
return maxClientVersion;
}
public long getPoolRetry()
{
return poolRetry * 1000;
}
public String getIoQueueName()
{
return ioQueueName;
}
public boolean isIoQueueAllowOverwrite()
{
return ioQueueAllowOverwrite;
}
public Restriction getDoorRestriction()
{
return doorRestriction;
}
public CheckStagePermission getCheckStagePermission()
{
return checkStagePermission;
}
public LoginStrategy createLoginStrategy(CellEndpoint cell)
{
UnionLoginStrategy union = new UnionLoginStrategy();
if (isAuthorizationStrong || isAuthorizationRequired) {
RemoteLoginStrategy loginStrategy = new RemoteLoginStrategy(new CellStub(cell, gPlazma, 30000));
union.setLoginStrategies(Collections.singletonList(loginStrategy));
}
if (!isAuthorizationStrong) {
union.setAnonymousAccess(anonymousAccessLevel);
}
return new CachingLoginStrategy(union, 1, Long.MAX_VALUE, TimeUnit.MILLISECONDS);
}
public PoolManagerStub createPoolManagerStub(CellEndpoint cellEndpoint, CellAddressCore address, PoolManagerHandler handler)
{
PoolManagerStub stub = new PoolManagerStub();
stub.setCellEndpoint(cellEndpoint);
stub.setCellAddress(address);
stub.setHandler(handler);
stub.setMaximumPoolManagerTimeout(20000);
stub.setMaximumPoolManagerTimeoutUnit(TimeUnit.MILLISECONDS);
return stub;
}
public CellStub createPinManagerStub(CellEndpoint cell)
{
return new CellStub(cell, pinManager);
}
}