package org.dcache.webadmin.view;
import org.apache.wicket.Component;
import org.apache.wicket.Page;
import org.apache.wicket.Session;
import org.apache.wicket.authorization.strategies.CompoundAuthorizationStrategy;
import org.apache.wicket.authorization.strategies.page.SimplePageAuthorizationStrategy;
import org.apache.wicket.authroles.authorization.strategies.role.RoleAuthorizationStrategy;
import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
import org.apache.wicket.core.request.mapper.CryptoMapper;
import org.apache.wicket.protocol.http.WebApplication;
import org.apache.wicket.protocol.https.HttpsConfig;
import org.apache.wicket.protocol.https.HttpsMapper;
import org.apache.wicket.protocol.https.Scheme;
import org.apache.wicket.request.IRequestHandler;
import org.apache.wicket.request.Request;
import org.apache.wicket.request.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Required;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import dmg.cells.nucleus.CellEndpoint;
import dmg.cells.nucleus.CellMessageSender;
import dmg.cells.nucleus.CellPath;
import org.dcache.auth.LoginStrategy;
import org.dcache.cells.CellStub;
import org.dcache.services.login.RemoteLoginStrategy;
import org.dcache.webadmin.controller.ActiveTransfersService;
import org.dcache.webadmin.controller.AlarmDisplayService;
import org.dcache.webadmin.controller.CellAdminService;
import org.dcache.webadmin.controller.CellsService;
import org.dcache.webadmin.controller.IBillingService;
import org.dcache.webadmin.controller.InfoService;
import org.dcache.webadmin.controller.LinkGroupsService;
import org.dcache.webadmin.controller.LogInService;
import org.dcache.webadmin.controller.PoolAdminService;
import org.dcache.webadmin.controller.PoolGroupService;
import org.dcache.webadmin.controller.PoolQueuesService;
import org.dcache.webadmin.controller.PoolSelectionSetupService;
import org.dcache.webadmin.controller.PoolSpaceService;
import org.dcache.webadmin.controller.TapeTransfersService;
import org.dcache.webadmin.controller.exceptions.LogInServiceException;
import org.dcache.webadmin.controller.impl.AlwaysFailLoginService;
import org.dcache.webadmin.controller.impl.LoginStrategyLogInService;
import org.dcache.webadmin.controller.util.ThumbnailPanelProvider;
import org.dcache.webadmin.view.beans.WebAdminInterfaceSession;
import org.dcache.webadmin.view.pages.AuthenticatedWebPage;
import org.dcache.webadmin.view.pages.activetransfers.ActiveTransfersPage;
import org.dcache.webadmin.view.pages.alarms.AlarmsPage;
import org.dcache.webadmin.view.pages.billingplots.BillingPlots;
import org.dcache.webadmin.view.pages.celladmin.CellAdmin;
import org.dcache.webadmin.view.pages.cellservices.CellServices;
import org.dcache.webadmin.view.pages.dcacheservices.DCacheServices;
import org.dcache.webadmin.view.pages.login.LogIn;
import org.dcache.webadmin.view.pages.pooladmin.PoolAdmin;
import org.dcache.webadmin.view.pages.poolgroupview.PoolGroupView;
import org.dcache.webadmin.view.pages.poollist.PoolList;
import org.dcache.webadmin.view.pages.poolqueues.PoolQueuePlots;
import org.dcache.webadmin.view.pages.poolqueues.PoolQueues;
import org.dcache.webadmin.view.pages.poolselectionsetup.PoolSelectionSetup;
import org.dcache.webadmin.view.pages.tapetransferqueue.TapeTransferQueue;
import org.dcache.webadmin.view.panels.navigation.BasicNavigationPanel;
import org.dcache.webadmin.view.util.Role;
/**
* This is the main application object for the whole Webadmin-Interface
*
* @author jans
*/
public class WebAdminInterface extends WebApplication implements CellMessageSender
{
public static final String MISSING_RESOURCE_KEY = "missing.resource";
private static final long LOGIN_CELLSTUB_TIMEOUT = 5000;
private static final List<Class<? extends Component>> ADMIN_PAGES
= new ArrayList<Class<? extends Component>>(
Arrays.asList(PoolAdmin.class, CellAdmin.class,
AlarmsPage.class));
private static final Logger _log
= LoggerFactory.getLogger(WebAdminInterface.class);
private CellEndpoint _cellEndpoint;
private LogInService _logInService = new AlwaysFailLoginService();
private PoolSpaceService _poolSpaceService;
private PoolQueuesService _poolQueuesService;
private PoolGroupService _poolGroupService;
private CellsService _cellsService;
private InfoService _infoService;
private PoolAdminService _poolAdminService;
private CellAdminService _cellAdminService;
private LinkGroupsService _linkGroupsService;
private ActiveTransfersService _activeTransfersService;
private PoolSelectionSetupService _poolSelectionSetupService;
private TapeTransfersService _tapeTransfersService;
private IBillingService _billingService;
private AlarmDisplayService _alarmDisplayService;
private ThumbnailPanelProvider _thumbnailPanelProvider;
private String _dcacheName;
private String _dcacheDescription;
private String _authDestination;
private int _adminGid;
private int _httpsPort;
private int _httpPort;
private boolean _generatePlots = false;
private boolean _poolQueuePlotsEnabled = false;
private boolean _authenticatedMode = false;
public ActiveTransfersService getActiveTransfersService() {
return _activeTransfersService;
}
public List<Class<? extends Component>> getAdminOnlyPages() {
return Collections.unmodifiableList(ADMIN_PAGES);
}
public AlarmDisplayService getAlarmDisplayService() {
return _alarmDisplayService;
}
public IBillingService getBillingService() {
return _billingService;
}
public CellAdminService getCellAdminService() {
return _cellAdminService;
}
public CellsService getCellsService() {
return _cellsService;
}
public String getDcacheName() {
return _dcacheName;
}
public String getDcacheDescription() {
return _dcacheDescription;
}
@Override
public Class<? extends Page> getHomePage() {
return DCacheServices.class;
}
public InfoService getInfoService() {
return _infoService;
}
public LinkGroupsService getLinkGroupsService() {
return _linkGroupsService;
}
public LogInService getLogInService() {
return _logInService;
}
public PoolAdminService getPoolAdminService() {
return _poolAdminService;
}
public PoolGroupService getPoolGroupService() {
return _poolGroupService;
}
public PoolQueuesService getPoolQueuesService() {
return _poolQueuesService;
}
public PoolSelectionSetupService getPoolSelectionSetupService() {
return _poolSelectionSetupService;
}
public PoolSpaceService getPoolSpaceService() {
return _poolSpaceService;
}
public TapeTransfersService getTapeTransfersService() {
return _tapeTransfersService;
}
public ThumbnailPanelProvider getThumbnailPanelProvider() {
return _thumbnailPanelProvider;
}
public boolean getAuthenticatedMode() {
return _authenticatedMode;
}
@Override
public Session newSession(Request request, Response response) {
return new WebAdminInterfaceSession(request);
}
@Required
public void setActiveTransfersService(
ActiveTransfersService activeTransfersService) {
_activeTransfersService = activeTransfersService;
}
@Required
public void setAdminGid(int adminGid) {
_adminGid = adminGid;
}
@Required
public void setAlarmDisplayService(AlarmDisplayService alarmDisplayService) {
_alarmDisplayService = alarmDisplayService;
}
@Required
public void setAuthDestination(String authDestination) {
_authDestination = authDestination;
}
@Required
public void setAuthenticatedMode(boolean authenticated) {
_authenticatedMode = authenticated;
}
@Required
public void setBillingService(IBillingService billingService) {
_billingService = billingService;
}
@Required
public void setCellAdminService(CellAdminService cellAdminService) {
_cellAdminService = cellAdminService;
}
@Required
public void setHttpPort(int port) {
_httpPort = port;
}
@Required
public void setHttpsPort(int port) {
_httpsPort = port;
}
@Override
public void setCellEndpoint(CellEndpoint endpoint) {
_cellEndpoint = endpoint;
}
@Required
public void setCellsService(CellsService cellsService) {
_cellsService = cellsService;
}
@Required
public void setDcacheName(String dCacheName) {
_dcacheName = dCacheName;
}
@Required
public void setDcacheDescription(String description) {
_dcacheDescription = description;
}
@Required
public void setGeneratePlots(boolean generatePlots) {
_generatePlots = generatePlots;
}
@Required
public void setInfoService(InfoService infoService) {
_infoService = infoService;
}
@Required
public void setLinkGroupsService(LinkGroupsService linkGroupsService) {
_linkGroupsService = linkGroupsService;
}
@Required
public void setPoolAdminService(PoolAdminService poolAdminService) {
_poolAdminService = poolAdminService;
}
@Required
public void setPoolGroupService(PoolGroupService poolGroupService) {
_poolGroupService = poolGroupService;
}
@Required
public void setPoolQueuePlotsEnabled(boolean enabled) {
_poolQueuePlotsEnabled = enabled;
}
@Required
public void setPoolQueuesService(PoolQueuesService poolQueuesService) {
_poolQueuesService = poolQueuesService;
}
@Required
public void setPoolSelectionSetupService(
PoolSelectionSetupService poolSelectionSetupService) {
_poolSelectionSetupService = poolSelectionSetupService;
}
@Required
public void setPoolSpaceService(PoolSpaceService poolSpaceService) {
_poolSpaceService = poolSpaceService;
}
@Required
public void setTapeTransfersService(
TapeTransfersService tapeTransfersService) {
_tapeTransfersService = tapeTransfersService;
}
@Required
public void setThumbnailPanelProvider(ThumbnailPanelProvider provider) {
_thumbnailPanelProvider = provider;
}
@Override
protected void init() {
super.init();
setAuthorizationStrategies();
getApplicationSettings().setPageExpiredErrorPage(LogIn.class);
setRootRequestMapper(new CryptoMapper(getRootRequestMapper(), this));
mountBookmarkablePages();
markAdminOnlyPages();
if (getAuthenticatedMode()) {
setRootRequestMapper(new HttpsMapper(getRootRequestMapper(),
new HttpsConfig(_httpPort, _httpsPort)) {
@Override
protected Scheme getDesiredSchemeFor(IRequestHandler handler)
{
Scheme desiredSchemeFor = super.getDesiredSchemeFor(handler);
return desiredSchemeFor == Scheme.HTTP ? Scheme.ANY : desiredSchemeFor;
}
});
}
}
private void markAdminOnlyPages() {
for (final Class<? extends Component> adminPage : ADMIN_PAGES) {
MetaDataRoleAuthorizationStrategy.authorize(adminPage, Role.ADMIN);
}
}
private void mountBookmarkablePages() {
/*
* warning changes in the pagenames/urls here may affect
* LegacyForwardHandler in Jettycell - always doublecheck when making
* changes
*/
mountPage("login", LogIn.class);
mountPage("cellinfo", CellServices.class);
mountPage("queueinfo", PoolQueues.class);
mountPage("usageinfo", PoolList.class);
mountPage("poolgroups", PoolGroupView.class);
mountPage("pooladmin", PoolAdmin.class);
mountPage("celladmin", CellAdmin.class);
mountPage("transfers", ActiveTransfersPage.class);
mountPage("poolinfo", PoolSelectionSetup.class);
mountPage("tapetransfers", TapeTransferQueue.class);
mountPage("alarms", AlarmsPage.class);
if (_generatePlots) {
_billingService.initialize();
mountPage("billingplots", BillingPlots.class);
} else {
BasicNavigationPanel.removeBillingPage("The httpd.enable.plots.billing property is false");
}
if (_poolQueuePlotsEnabled) {
mountPage("poolqueueplots", PoolQueuePlots.class);
} else {
BasicNavigationPanel.removePoolQueuePlotsPage("The httpd.enable.plots.pool-queue property is false");
}
}
private void setAuthorizationStrategies() {
if (getAuthenticatedMode()) {
LoginStrategy loginStrategy
= new RemoteLoginStrategy(new CellStub(_cellEndpoint,
new CellPath(_authDestination),
LOGIN_CELLSTUB_TIMEOUT));
LoginStrategyLogInService loginService
= new LoginStrategyLogInService();
loginService.setLoginStrategy(loginStrategy);
loginService.setAdminGid(_adminGid);
_logInService = loginService;
}
SimplePageAuthorizationStrategy simplePageStrategy
= new SimplePageAuthorizationStrategy(AuthenticatedWebPage.class,
LogIn.class) {
@Override
protected boolean isAuthorized() {
/*
* we want the automatic sign-in here,
* not on the beforeRender() of the LogIn page as it was;
* we also want this to be only for cert signin
*/
boolean signedIn
= ((WebAdminInterfaceSession) Session.get()).isSignedIn();
if (!signedIn) {
try {
LogIn.signInWithCert(_logInService);
signedIn = true;
} catch (IllegalArgumentException | LogInServiceException e) {
_log.debug("could not automatically authorize "
+ "using browser certificate: {}",
e.toString());
}
}
return signedIn;
}
};
RoleAuthorizationStrategy roleStrategy
= new RoleAuthorizationStrategy(
roles -> {
_log.debug("checking {}", roles.toString());
boolean hasAnyRoles = ((WebAdminInterfaceSession)
Session.get()).hasAnyRole(roles);
_log.debug("results in: {}", hasAnyRoles);
return hasAnyRoles;
});
final CompoundAuthorizationStrategy compoundStrategy
= new CompoundAuthorizationStrategy();
compoundStrategy.add(simplePageStrategy);
compoundStrategy.add(roleStrategy);
getSecuritySettings().setAuthorizationStrategy(compoundStrategy);
}
}