Search in sources :

Example 1 with MacaroonContext

use of org.dcache.macaroons.MacaroonContext in project dcache by dCache.

the class MacaroonRequestHandler method buildMacaroon.

private String buildMacaroon(String target, Request request) throws ErrorResponseException {
    checkValidRequest(request.isSecure(), "Not secure transport");
    if (Subjects.isNobody(getSubject())) {
        throw new ErrorResponseException(SC_UNAUTHORIZED, "Authentication required");
    }
    MacaroonContext context = buildContext(target, request);
    MacaroonRequest macaroonRequest = parseJSON(request);
    try {
        List<Caveat> caveats = new ArrayList<>();
        List<Caveat> beforeCaveats = new ArrayList<>();
        for (String serialisedCaveat : macaroonRequest.getCaveats()) {
            Caveat caveat = new Caveat(serialisedCaveat);
            (caveat.hasType(BEFORE) ? beforeCaveats : caveats).add(caveat);
        }
        macaroonRequest.getValidity().map(Duration::parse).map(Instant.now()::plus).map(i -> new Caveat(BEFORE, i)).ifPresent(beforeCaveats::add);
        Instant expiry = calculateExpiry(context, beforeCaveats);
        MacaroonProcessor.MacaroonBuildResult result = _processor.buildMacaroon(expiry, context, caveats);
        request.setAttribute(MACAROON_ID_ATTRIBUTE, result.getId());
        return result.getMacaroon();
    } catch (DateTimeParseException e) {
        throw new ErrorResponseException(SC_BAD_REQUEST, "Bad validity value: " + e.getMessage());
    } catch (InvalidCaveatException e) {
        throw new ErrorResponseException(SC_BAD_REQUEST, "Bad requested caveat: " + e.getMessage());
    } catch (InternalErrorException e) {
        throw new ErrorResponseException(SC_INTERNAL_SERVER_ERROR, "Internal error: " + e.getMessage());
    }
}
Also used : Request(org.eclipse.jetty.server.Request) Restriction(org.dcache.auth.attributes.Restriction) Subjects(org.dcache.auth.Subjects) URISyntaxException(java.net.URISyntaxException) LoggerFactory(org.slf4j.LoggerFactory) Expiry(org.dcache.auth.attributes.Expiry) GsonBuilder(com.google.gson.GsonBuilder) Preconditions.checkArgument(com.google.common.base.Preconditions.checkArgument) AuthenticationHandler(org.dcache.http.AuthenticationHandler) JSONObject(org.json.JSONObject) CharStreams(com.google.common.io.CharStreams) PathMapper(org.dcache.http.PathMapper) Duration(java.time.Duration) URI(java.net.URI) CDC(dmg.cells.nucleus.CDC) PrintWriter(java.io.PrintWriter) ImmutableSet(com.google.common.collect.ImmutableSet) Collection(java.util.Collection) Caveat(org.dcache.macaroons.Caveat) Instant(java.time.Instant) MaxUploadSize(org.dcache.auth.attributes.MaxUploadSize) Objects(java.util.Objects) BEFORE(org.dcache.macaroons.CaveatType.BEFORE) DateTimeParseException(java.time.format.DateTimeParseException) List(java.util.List) InvalidCaveatException(org.dcache.macaroons.InvalidCaveatException) Optional(java.util.Optional) AccessController(java.security.AccessController) TRUE(java.lang.Boolean.TRUE) LoginAttribute(org.dcache.auth.attributes.LoginAttribute) JsonParseException(com.google.gson.JsonParseException) FsPath(diskCacheV111.util.FsPath) SC_INTERNAL_SERVER_ERROR(javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR) AbstractHandler(org.eclipse.jetty.server.handler.AbstractHandler) CellAddressCore(dmg.cells.nucleus.CellAddressCore) ArrayList(java.util.ArrayList) HttpServletRequest(javax.servlet.http.HttpServletRequest) CellIdentityAware(dmg.cells.nucleus.CellIdentityAware) HomeDirectory(org.dcache.auth.attributes.HomeDirectory) MacaroonContext(org.dcache.macaroons.MacaroonContext) SC_UNAUTHORIZED(javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED) MacaroonProcessor(org.dcache.macaroons.MacaroonProcessor) InvalidCaveatException.checkCaveat(org.dcache.macaroons.InvalidCaveatException.checkCaveat) Logger(org.slf4j.Logger) PrefixRestriction(org.dcache.auth.attributes.PrefixRestriction) HttpServletResponse(javax.servlet.http.HttpServletResponse) IOException(java.io.IOException) DenyActivityRestriction(org.dcache.auth.attributes.DenyActivityRestriction) Subject(javax.security.auth.Subject) NDC(org.dcache.util.NDC) Strings.emptyToNull(com.google.common.base.Strings.emptyToNull) ChronoUnit(java.time.temporal.ChronoUnit) RootDirectory(org.dcache.auth.attributes.RootDirectory) SC_BAD_REQUEST(javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST) InternalErrorException(org.dcache.macaroons.InternalErrorException) Required(org.springframework.beans.factory.annotation.Required) Collections(java.util.Collections) InvalidCaveatException(org.dcache.macaroons.InvalidCaveatException) Caveat(org.dcache.macaroons.Caveat) InvalidCaveatException.checkCaveat(org.dcache.macaroons.InvalidCaveatException.checkCaveat) Instant(java.time.Instant) ArrayList(java.util.ArrayList) InternalErrorException(org.dcache.macaroons.InternalErrorException) MacaroonProcessor(org.dcache.macaroons.MacaroonProcessor) MacaroonContext(org.dcache.macaroons.MacaroonContext) DateTimeParseException(java.time.format.DateTimeParseException)

Example 2 with MacaroonContext

use of org.dcache.macaroons.MacaroonContext in project dcache by dCache.

the class MacaroonLoginStrategy method login.

@Override
public LoginReply login(Subject subject) throws CacheException {
    LOGGER.debug("Login attempted: {}", subject);
    Origin origin = extractClientIP(subject);
    String macaroon = extractCredential(subject);
    try {
        MacaroonContext context = processor.expandMacaroon(macaroon, origin.getAddress());
        LoginReply reply = new LoginReply();
        FsPath root = context.getRoot().orElse(FsPath.ROOT);
        Set<LoginAttribute> attributes = reply.getLoginAttributes();
        attributes.add(new HomeDirectory(context.getHome().orElse(FsPath.ROOT)));
        attributes.add(new RootDirectory(root));
        context.getExpiry().map(Expiry::new).ifPresent(attributes::add);
        context.getPath().map(root::chroot).map(PrefixRestriction::new).ifPresent(attributes::add);
        context.getAllowedActivities().map(EnumSet::complementOf).map(DenyActivityRestriction::new).ifPresent(attributes::add);
        context.getMaxUpload().ifPresent(s -> attributes.add(new MaxUploadSize(s)));
        Set<Principal> principals = reply.getSubject().getPrincipals();
        principals.add(new UidPrincipal(context.getUid()));
        principals.addAll(asGidPrincipals(context.getGids()));
        principals.add(new UserNamePrincipal(context.getUsername()));
        principals.add(origin);
        principals.add(new MacaroonPrincipal(context.getId()));
        LOGGER.debug("Login successful: {}", reply);
        return reply;
    } catch (InvalidMacaroonException e) {
        throw new PermissionDeniedCacheException("macaroon login denied: " + e.getMessage());
    }
}
Also used : HomeDirectory(org.dcache.auth.attributes.HomeDirectory) LoginAttribute(org.dcache.auth.attributes.LoginAttribute) MaxUploadSize(org.dcache.auth.attributes.MaxUploadSize) EnumSet(java.util.EnumSet) RootDirectory(org.dcache.auth.attributes.RootDirectory) MacaroonContext(org.dcache.macaroons.MacaroonContext) PermissionDeniedCacheException(diskCacheV111.util.PermissionDeniedCacheException) InvalidMacaroonException(org.dcache.macaroons.InvalidMacaroonException) Principal(java.security.Principal) FsPath(diskCacheV111.util.FsPath)

Example 3 with MacaroonContext

use of org.dcache.macaroons.MacaroonContext in project dcache by dCache.

the class MacaroonRequestHandler method buildContext.

private MacaroonContext buildContext(String target, Request request) throws ErrorResponseException {
    MacaroonContext context = new MacaroonContext();
    FsPath desiredPath = _pathMapper.asDcachePath(request, target);
    FsPath userRoot = FsPath.ROOT;
    FsPath prefixRestrictionPath = null;
    for (LoginAttribute attr : AuthenticationHandler.getLoginAttributes(request)) {
        if (attr instanceof HomeDirectory) {
            context.setHome(FsPath.ROOT.resolve(((HomeDirectory) attr).getHome()));
        } else if (attr instanceof RootDirectory) {
            userRoot = FsPath.ROOT.resolve(((RootDirectory) attr).getRoot());
        } else if (attr instanceof Expiry) {
            context.updateExpiry(((Expiry) attr).getExpiry());
        } else if (attr instanceof DenyActivityRestriction) {
            context.removeActivities(((DenyActivityRestriction) attr).getDenied());
        } else if (attr instanceof PrefixRestriction) {
            ImmutableSet<FsPath> paths = ((PrefixRestriction) attr).getPrefixes();
            if (target.equals("/")) {
                checkArgument(paths.size() == 1, "Cannot serialise with multiple path restrictions");
                prefixRestrictionPath = paths.iterator().next();
            } else {
                prefixRestrictionPath = paths.stream().filter(desiredPath::hasPrefix).findFirst().orElseThrow(() -> new ErrorResponseException(SC_BAD_REQUEST, "Bad request path: Desired path not within existing path"));
            }
        } else if (attr instanceof Restriction) {
            throw new ErrorResponseException(SC_BAD_REQUEST, "Cannot serialise restriction " + attr.getClass().getSimpleName());
        } else if (attr instanceof MaxUploadSize) {
            try {
                context.updateMaxUpload(((MaxUploadSize) attr).getMaximumSize());
            } catch (InvalidCaveatException e) {
                throw new ErrorResponseException(SC_BAD_REQUEST, "Cannot add max-upload: " + e.getMessage());
            }
        }
    }
    Subject subject = getSubject();
    context.setUid(Subjects.getUid(subject));
    context.setGids(Subjects.getGids(subject));
    context.setUsername(Subjects.getUserName(subject));
    FsPath effectiveRoot = _pathMapper.effectiveRoot(userRoot, m -> new ErrorResponseException(SC_BAD_REQUEST, m));
    context.setRoot(effectiveRoot);
    FsPath path = prefixRestrictionPath != null ? prefixRestrictionPath : target.equals("/") ? null : desiredPath;
    if (path != null) {
        context.setPath(path.stripPrefix(effectiveRoot));
    }
    return context;
}
Also used : PrefixRestriction(org.dcache.auth.attributes.PrefixRestriction) InvalidCaveatException(org.dcache.macaroons.InvalidCaveatException) HomeDirectory(org.dcache.auth.attributes.HomeDirectory) LoginAttribute(org.dcache.auth.attributes.LoginAttribute) MaxUploadSize(org.dcache.auth.attributes.MaxUploadSize) RootDirectory(org.dcache.auth.attributes.RootDirectory) Subject(javax.security.auth.Subject) MacaroonContext(org.dcache.macaroons.MacaroonContext) Restriction(org.dcache.auth.attributes.Restriction) PrefixRestriction(org.dcache.auth.attributes.PrefixRestriction) DenyActivityRestriction(org.dcache.auth.attributes.DenyActivityRestriction) Expiry(org.dcache.auth.attributes.Expiry) DenyActivityRestriction(org.dcache.auth.attributes.DenyActivityRestriction) FsPath(diskCacheV111.util.FsPath)

Aggregations

FsPath (diskCacheV111.util.FsPath)3 HomeDirectory (org.dcache.auth.attributes.HomeDirectory)3 LoginAttribute (org.dcache.auth.attributes.LoginAttribute)3 MaxUploadSize (org.dcache.auth.attributes.MaxUploadSize)3 Subject (javax.security.auth.Subject)2 DenyActivityRestriction (org.dcache.auth.attributes.DenyActivityRestriction)2 Expiry (org.dcache.auth.attributes.Expiry)2 PrefixRestriction (org.dcache.auth.attributes.PrefixRestriction)2 Restriction (org.dcache.auth.attributes.Restriction)2 RootDirectory (org.dcache.auth.attributes.RootDirectory)2 MacaroonContext (org.dcache.macaroons.MacaroonContext)2 Preconditions.checkArgument (com.google.common.base.Preconditions.checkArgument)1 Strings.emptyToNull (com.google.common.base.Strings.emptyToNull)1 ImmutableSet (com.google.common.collect.ImmutableSet)1 CharStreams (com.google.common.io.CharStreams)1 GsonBuilder (com.google.gson.GsonBuilder)1 JsonParseException (com.google.gson.JsonParseException)1 PermissionDeniedCacheException (diskCacheV111.util.PermissionDeniedCacheException)1 CDC (dmg.cells.nucleus.CDC)1 CellAddressCore (dmg.cells.nucleus.CellAddressCore)1