Search in sources :

Example 1 with Restriction

use of org.dcache.auth.attributes.Restriction in project dcache by dCache.

the class ScopeBasedAuthzProfile method buildRestriction.

private Restriction buildRestriction(List<AuthorisationSupplier> scopes) {
    Map<FsPath, MultiTargetedRestriction.Authorisation> authorisations = new HashMap<>();
    scopes.stream().map(s -> s.authorisation(prefix)).filter(Optional::isPresent).map(Optional::get).forEach(a -> {
        FsPath path = a.getPath();
        MultiTargetedRestriction.Authorisation existing = authorisations.get(path);
        if (existing != null) {
            Collection<Activity> combined = EnumSet.copyOf(existing.getActivity());
            combined.addAll(a.getActivity());
            a = new MultiTargetedRestriction.Authorisation(combined, path);
        }
        authorisations.put(path, a);
    });
    return new MultiTargetedRestriction(authorisations.values());
}
Also used : ExemptFromNamespaceChecks(org.dcache.auth.ExemptFromNamespaceChecks) MultiTargetedRestriction(org.dcache.auth.attributes.MultiTargetedRestriction) FsPath(diskCacheV111.util.FsPath) Preconditions.checkAuthentication(org.dcache.gplazma.util.Preconditions.checkAuthentication) Restriction(org.dcache.auth.attributes.Restriction) Collection(java.util.Collection) Set(java.util.Set) HashMap(java.util.HashMap) Streams(com.google.common.collect.Streams) Collectors(java.util.stream.Collectors) AuthenticationException(org.dcache.gplazma.AuthenticationException) ProfileResult(org.dcache.gplazma.oidc.ProfileResult) List(java.util.List) Principal(java.security.Principal) Map(java.util.Map) Objects.requireNonNull(java.util.Objects.requireNonNull) Activity(org.dcache.auth.attributes.Activity) Optional(java.util.Optional) JsonNode(com.fasterxml.jackson.databind.JsonNode) Collections(java.util.Collections) IdentityProvider(org.dcache.gplazma.oidc.IdentityProvider) EnumSet(java.util.EnumSet) Optional(java.util.Optional) HashMap(java.util.HashMap) MultiTargetedRestriction(org.dcache.auth.attributes.MultiTargetedRestriction) Activity(org.dcache.auth.attributes.Activity) FsPath(diskCacheV111.util.FsPath)

Example 2 with Restriction

use of org.dcache.auth.attributes.Restriction in project dcache by dCache.

the class ScitokensProfileTest method shouldAcceptSubdirReadScitokenScope.

@Test
public void shouldAcceptSubdirReadScitokenScope() throws Exception {
    given(aScitokensProfile().withPrefix("/prefix"));
    when(invoked().withIdP(anIp("MY-OP")).withStringClaim("scope", "read:/target"));
    assertThat(principals, hasItem(any(ExemptFromNamespaceChecks.class)));
    assertThat(restriction, isPresent());
    Restriction r = restriction.get();
    assertTrue(r.isRestricted(Activity.UPLOAD, FsPath.create("/my-file")));
    assertTrue(r.isRestricted(Activity.UPLOAD, FsPath.create("/prefix/my-file")));
    assertTrue(r.isRestricted(Activity.UPLOAD, FsPath.create("/other/my-file")));
    assertTrue(r.isRestricted(Activity.MANAGE, FsPath.create("/my-file")));
    assertTrue(r.isRestricted(Activity.MANAGE, FsPath.create("/prefix/my-file")));
    assertTrue(r.isRestricted(Activity.MANAGE, FsPath.create("/other/my-file")));
    assertTrue(r.isRestricted(Activity.DELETE, FsPath.create("/my-file")));
    assertTrue(r.isRestricted(Activity.DELETE, FsPath.create("/prefix/my-file")));
    assertTrue(r.isRestricted(Activity.DELETE, FsPath.create("/other/my-file")));
    assertTrue(r.isRestricted(Activity.UPDATE_METADATA, FsPath.create("/my-file")));
    assertTrue(r.isRestricted(Activity.UPDATE_METADATA, FsPath.create("/prefix/my-file")));
    assertTrue(r.isRestricted(Activity.UPDATE_METADATA, FsPath.create("/other/my-file")));
    assertTrue(r.isRestricted(Activity.DOWNLOAD, FsPath.create("/my-file")));
    assertTrue(r.isRestricted(Activity.DOWNLOAD, FsPath.create("/other/my-file")));
    assertTrue(r.isRestricted(Activity.DOWNLOAD, FsPath.create("/prefix/my-file")));
    assertFalse(r.isRestricted(Activity.DOWNLOAD, FsPath.create("/prefix/target/my-file")));
}
Also used : Restriction(org.dcache.auth.attributes.Restriction) Test(org.junit.Test)

Example 3 with Restriction

use of org.dcache.auth.attributes.Restriction in project dcache by dCache.

the class ScitokensProfileTest method shouldAcceptRootReadAndTargetWriteScitokenScope.

@Test
public void shouldAcceptRootReadAndTargetWriteScitokenScope() throws Exception {
    given(aScitokensProfile().withPrefix("/prefix"));
    when(invoked().withIdP(anIp("MY-OP")).withStringClaim("scope", "read:/ write:/target"));
    assertThat(principals, hasItem(any(ExemptFromNamespaceChecks.class)));
    assertThat(restriction, isPresent());
    Restriction r = restriction.get();
    assertTrue(r.isRestricted(Activity.DOWNLOAD, FsPath.create("/my-file")));
    assertTrue(r.isRestricted(Activity.UPLOAD, FsPath.create("/my-file")));
    assertTrue(r.isRestricted(Activity.UPDATE_METADATA, FsPath.create("/my-file")));
    assertTrue(r.isRestricted(Activity.MANAGE, FsPath.create("/my-file")));
    assertTrue(r.isRestricted(Activity.DELETE, FsPath.create("/my-file")));
    assertTrue(r.isRestricted(Activity.DOWNLOAD, FsPath.create("/other/my-file")));
    assertTrue(r.isRestricted(Activity.UPLOAD, FsPath.create("/other/my-file")));
    assertTrue(r.isRestricted(Activity.UPDATE_METADATA, FsPath.create("/other/my-file")));
    assertTrue(r.isRestricted(Activity.MANAGE, FsPath.create("/other/my-file")));
    assertTrue(r.isRestricted(Activity.DELETE, FsPath.create("/other/my-file")));
    assertFalse(r.isRestricted(Activity.DOWNLOAD, FsPath.create("/prefix/my-file")));
    assertTrue(r.isRestricted(Activity.UPLOAD, FsPath.create("/prefix/my-file")));
    assertTrue(r.isRestricted(Activity.UPDATE_METADATA, FsPath.create("/prefix/my-file")));
    assertTrue(r.isRestricted(Activity.MANAGE, FsPath.create("/prefix/my-file")));
    assertTrue(r.isRestricted(Activity.DELETE, FsPath.create("/prefix/my-file")));
    assertFalse(r.isRestricted(Activity.DOWNLOAD, FsPath.create("/prefix/target/my-file")));
    assertFalse(r.isRestricted(Activity.UPLOAD, FsPath.create("/prefix/target/my-file")));
    assertFalse(r.isRestricted(Activity.UPDATE_METADATA, FsPath.create("/prefix/target/my-file")));
    assertFalse(r.isRestricted(Activity.MANAGE, FsPath.create("/prefix/target/my-file")));
    assertFalse(r.isRestricted(Activity.DELETE, FsPath.create("/prefix/target/my-file")));
}
Also used : Restriction(org.dcache.auth.attributes.Restriction) Test(org.junit.Test)

Example 4 with Restriction

use of org.dcache.auth.attributes.Restriction in project dcache by dCache.

the class XrootdRedirectHandler method conditionallyHandleThirdPartyRequest.

/**
 * <p>Special handling of third-party requests. Distinguishes among
 * several different cases for the open and either returns a response directly to the caller or
 * proceeds with the usual mover open and redirect to the pool by returning <code>null</code>.
 * Also verifies the rendezvous information in the case of the destination server contacting
 * dCache as source.</p>
 *
 * <p>With the modified TPC lite (delegation) protocol, there is no
 * need to wait for the rendezvous destination check by comparing the open from the source.</p>
 *
 * <p>There is also the case where no delegated proxy exists but
 * a different authentication protocol (like ZTN/scitokens) is being used.  It seems that even
 * with delegation in this case the initiating client does not call open. A check for authz in
 * the opaque data has been added (03/21/2021).</p>
 */
private XrootdResponse<OpenRequest> conditionallyHandleThirdPartyRequest(OpenRequest req, LoginSessionInfo loginSessionInfo, Map<String, String> opaque, FsPath fsPath, String remoteHost) throws CacheException, XrootdException, ParseException {
    if (!_door.isReadAllowed(fsPath)) {
        throw new PermissionDeniedCacheException("Read permission denied");
    }
    Subject subject = loginSessionInfo.getSubject();
    Restriction restriction = loginSessionInfo.getRestriction();
    if ("placement".equals(opaque.get("tpc.stage"))) {
        FileStatus status = _door.getFileStatus(fsPath, subject, restriction, remoteHost);
        int fd = _door.nextTpcPlaceholder();
        _log.debug("placement response to {} sent to {} with fhandle {}.", req, remoteHost, fd);
        return new OpenResponse(req, fd, null, null, status);
    }
    String tpcKey = opaque.get("tpc.key");
    if (tpcKey == null) {
        _log.debug("{} –– not a third-party request.", req);
        // proceed as usual with mover + redirect
        return null;
    }
    if (opaque.containsKey(Cgi.AUTHZ.key())) {
        _log.debug("{} –– request contains authorization token.", req);
        // proceed as usual with mover + redirect
        return null;
    }
    enforceClientTlsIfDestinationRequiresItForTpc(opaque);
    /*
         * Check the session for the delegated credential to avoid hanging
         * in the case that tpc cgi have been passed by the destination
         * server even with TPC with delegation.
         */
    if (req.getSession().getDelegatedCredential() != null) {
        _log.debug("{} –– third-party request with delegation.", req);
        // proceed as usual with mover + redirect
        return null;
    }
    String slfn = req.getPath();
    XrootdTpcInfo info = _door.createOrGetRendezvousInfo(tpcKey);
    /*
         *  The request originated from the TPC destination server.
         *  If the client has not yet opened the file here,
         *  tells the destination to wait.  If the verification, including
         *  time to live, fails, the request is cancelled.  Otherwise,
         *  the destination is allowed to open the mover and get the
         *  normal redirect response.
         *
         *  Note that the tpc info is created by either the client or the
         *  server, whichever gets here first.  Verification of the key
         *  itself is implicit (it has been found in the map); correctness is
         *  further satisfied by matching org, host and file name.
         */
    if (opaque.containsKey("tpc.org")) {
        info.addInfoFromOpaque(slfn, opaque);
        switch(info.verify(remoteHost, slfn, opaque.get("tpc.org"))) {
            case READY:
                _log.debug("Open request {} from destination server, info {}: " + "OK to proceed.", req, info);
                /*
                     *  This means that the destination server open arrived
                     *  second, the client server open succeeded with
                     *  the correct permissions; proceed as usual
                     *  with mover + redirect.
                     */
                return null;
            case PENDING:
                _log.debug("Open request {} from destination server, info {}: " + "PENDING client open.", req, info);
                /*
                     *  This means that the destination server open arrived
                     *  first; return a wait-retry reply.
                     */
                return new AwaitAsyncResponse<>(req, 3);
            case CANCELLED:
                String error = info.isExpired() ? "ttl expired" : "dst, path or org" + " did not match";
                _log.warn("Open request {} from destination server, info {}: " + "CANCELLED: {}.", req, info, error);
                _door.removeTpcPlaceholder(info.getFd());
                return withError(req, kXR_InvalidRequest, "tpc rendezvous for " + tpcKey + ": " + error);
            case ERROR:
                /*
                     *  This means that the destination server requested open
                     *  before the client did, and the client did not have
                     *  read permissions on this file.
                     */
                error = "invalid open request (file permissions).";
                _log.warn("Open request {} from destination server, info {}: " + "ERROR: {}.", req, info, error);
                _door.removeTpcPlaceholder(info.getFd());
                return withError(req, kXR_InvalidRequest, "tpc rendezvous for " + tpcKey + ": " + error);
        }
    }
    /*
         *  The request originated from the TPC client, indicating door
         *  is the source.
         */
    if (opaque.containsKey("tpc.dst")) {
        _log.debug("Open request {} from client to door as source, " + "info {}: OK.", req, info);
        FileStatus status = _door.getFileStatus(fsPath, subject, restriction, remoteHost);
        int flags = status.getFlags();
        if ((flags & kXR_readable) != kXR_readable) {
            /*
                 * Update the info with ERROR, so when the destination checks
                 * it, an error can be returned.
                 */
            info.setStatus(Status.ERROR);
            return withError(req, kXR_InvalidRequest, "not allowed to read file.");
        }
        info.addInfoFromOpaque(slfn, opaque);
        return new OpenResponse(req, info.getFd(), null, null, status);
    }
    /*
         *  The request originated from the TPC client, indicating door
         *  is the destination.
         *
         *  First check for TLS capability if this is required.
         *
         *  Remove the rendezvous info (not needed),
         *  allow mover to start and redirect the client to the pool.
         *
         *  It is not necessary to delegate the tpc information through the
         *  protocol, particularly the rendezvous key, because it is part of
         *  the opaque data, and if any of the opaque tpc info is missing
         *  from redirected call to the pool, the transfer will fail.
         *
         *  However, the calling method will need to fetch a delegated
         *  proxy credential and add that to the protocol.
         */
    if (opaque.containsKey("tpc.src")) {
        _log.debug("Open request {} from client to door as destination: OK;" + "removing info {}.", req, info);
        _door.removeTpcPlaceholder(info.getFd());
        // proceed as usual with mover + redirect
        return null;
    }
    /*
         *  Something went wrong.
         */
    String error = String.format("Request metadata is invalid: %s: %s, %s.", req, fsPath, remoteHost);
    throw new CacheException(CacheException.THIRD_PARTY_TRANSFER_FAILED, error);
}
Also used : Restriction(org.dcache.auth.attributes.Restriction) PermissionDeniedCacheException(diskCacheV111.util.PermissionDeniedCacheException) AwaitAsyncResponse(org.dcache.xrootd.protocol.messages.AwaitAsyncResponse) FileStatus(org.dcache.xrootd.util.FileStatus) XrootdTpcInfo(org.dcache.xrootd.tpc.XrootdTpcInfo) FileIsNewCacheException(diskCacheV111.util.FileIsNewCacheException) FileExistsCacheException(diskCacheV111.util.FileExistsCacheException) FileNotFoundCacheException(diskCacheV111.util.FileNotFoundCacheException) NotFileCacheException(diskCacheV111.util.NotFileCacheException) TimeoutCacheException(diskCacheV111.util.TimeoutCacheException) CacheException(diskCacheV111.util.CacheException) PermissionDeniedCacheException(diskCacheV111.util.PermissionDeniedCacheException) OpenResponse(org.dcache.xrootd.protocol.messages.OpenResponse) Subject(javax.security.auth.Subject)

Example 5 with Restriction

use of org.dcache.auth.attributes.Restriction in project dcache by dCache.

the class XrootdRedirectHandler method doOnStatx.

@Override
protected XrootdResponse<StatxRequest> doOnStatx(ChannelHandlerContext ctx, StatxRequest req) throws XrootdException {
    if (req.getPaths().length == 0) {
        throw new XrootdException(kXR_ArgMissing, "no paths specified");
    }
    try {
        FsPath[] paths = new FsPath[req.getPaths().length];
        for (int i = 0; i < paths.length; i++) {
            paths[i] = createFullPath(req.getPaths()[i]);
        }
        LoginSessionInfo loginSessionInfo = sessionInfo();
        Subject subject = loginSessionInfo.getSubject();
        Restriction restriction = loginSessionInfo.getRestriction();
        return new StatxResponse(req, _door.getMultipleFileStatuses(paths, subject, restriction));
    } catch (TimeoutCacheException e) {
        throw xrootdException(e.getRc(), "Internal timeout");
    } catch (PermissionDeniedCacheException e) {
        throw xrootdException(e);
    } catch (CacheException e) {
        throw xrootdException(e.getRc(), String.format("Failed to open file (%s [%d])", e.getMessage(), e.getRc()));
    }
}
Also used : Restriction(org.dcache.auth.attributes.Restriction) PermissionDeniedCacheException(diskCacheV111.util.PermissionDeniedCacheException) FileIsNewCacheException(diskCacheV111.util.FileIsNewCacheException) FileExistsCacheException(diskCacheV111.util.FileExistsCacheException) FileNotFoundCacheException(diskCacheV111.util.FileNotFoundCacheException) NotFileCacheException(diskCacheV111.util.NotFileCacheException) TimeoutCacheException(diskCacheV111.util.TimeoutCacheException) CacheException(diskCacheV111.util.CacheException) PermissionDeniedCacheException(diskCacheV111.util.PermissionDeniedCacheException) StatxResponse(org.dcache.xrootd.protocol.messages.StatxResponse) XrootdException(org.dcache.xrootd.core.XrootdException) Subject(javax.security.auth.Subject) FsPath(diskCacheV111.util.FsPath) TimeoutCacheException(diskCacheV111.util.TimeoutCacheException)

Aggregations

Restriction (org.dcache.auth.attributes.Restriction)44 Subject (javax.security.auth.Subject)23 FsPath (diskCacheV111.util.FsPath)13 Test (org.junit.Test)13 PermissionDeniedCacheException (diskCacheV111.util.PermissionDeniedCacheException)12 CacheException (diskCacheV111.util.CacheException)11 FileNotFoundCacheException (diskCacheV111.util.FileNotFoundCacheException)10 TimeoutCacheException (diskCacheV111.util.TimeoutCacheException)10 FileExistsCacheException (diskCacheV111.util.FileExistsCacheException)7 FileIsNewCacheException (diskCacheV111.util.FileIsNewCacheException)7 FileCorruptedCacheException (diskCacheV111.util.FileCorruptedCacheException)5 NotDirCacheException (diskCacheV111.util.NotDirCacheException)5 SRMAuthorizationException (org.dcache.srm.SRMAuthorizationException)5 SRMInternalErrorException (org.dcache.srm.SRMInternalErrorException)5 Principal (java.security.Principal)4 SRMException (org.dcache.srm.SRMException)4 SRMInvalidPathException (org.dcache.srm.SRMInvalidPathException)4 ApiOperation (io.swagger.annotations.ApiOperation)3 ApiResponses (io.swagger.annotations.ApiResponses)3 ArrayList (java.util.ArrayList)3