Search in sources :

Example 6 with InvalidationException

use of io.hops.hopsworks.jwt.exception.InvalidationException in project hopsworks by logicalclocks.

the class AuthService method needLogin.

private boolean needLogin(HttpServletRequest req, Users user) {
    String remoteUser = req.getRemoteUser();
    Users tokenUser = jWTHelper.getUserPrincipal(req);
    boolean validToken = jWTHelper.validToken(req, settings.getJWTIssuer());
    if (isUserLoggedIn(remoteUser, tokenUser, validToken, user)) {
        return false;
    } else if (isSomeoneElseLoggedIn(remoteUser, tokenUser, validToken, user)) {
        try {
            logoutAndInvalidateSession(req);
        } catch (InvalidationException | UserException ex) {
            LOGGER.log(Level.SEVERE, null, ex.getMessage());
        }
    } else if (validToken || remoteUser != null) {
        if (remoteUser != null) {
            try {
                logoutSession(req);
            } catch (UserException ex) {
                LOGGER.log(Level.SEVERE, null, ex);
            }
        }
        if (validToken) {
            try {
                jWTHelper.invalidateToken(req);
            } catch (InvalidationException ex) {
                LOGGER.log(Level.SEVERE, null, ex);
            }
        }
    }
    return true;
}
Also used : Users(io.hops.hopsworks.persistence.entity.user.Users) UserException(io.hops.hopsworks.exceptions.UserException) InvalidationException(io.hops.hopsworks.jwt.exception.InvalidationException)

Example 7 with InvalidationException

use of io.hops.hopsworks.jwt.exception.InvalidationException in project hopsworks by logicalclocks.

the class AirflowManager method recover.

/**
 * Recover security material for Airflow after restart. Read all active material from the database.
 * Check if JWT exists in the local filesystem and it is valid.
 * If not try to create a new one. Finally, materialize X.509 for project specific user.
 */
private void recover() {
    LOG.log(Level.FINE, "Starting Airflow manager recovery");
    List<MaterializedJWT> failed2recover = new ArrayList<>();
    Project project = null;
    Users user = null;
    // Get last known state from storage
    for (MaterializedJWT material : materializedJWTFacade.findAll4Airflow()) {
        LOG.log(Level.FINEST, "Recovering material: " + material.getIdentifier().getProjectId() + " - " + material.getIdentifier().getUserId());
        project = projectFacade.find(material.getIdentifier().getProjectId());
        user = userFacade.find(material.getIdentifier().getUserId());
        if (project == null || user == null) {
            LOG.log(Level.WARNING, "Error while recovering Project with ID: " + material.getIdentifier().getProjectId() + " and User ID: " + material.getIdentifier().getUserId() + ". Project or user is null");
            failed2recover.add(material);
            continue;
        }
        Path tokenFile = Paths.get(getProjectSecretsDirectory(user.getUsername()).toString(), getTokenFileName(project.getName(), user.getUsername()));
        AirflowJWT airflowJWT;
        String token = null;
        String materialIdentifier = "Project: " + project.getName() + " - User: " + user.getUsername();
        try {
            // First try to read JWT from the filesystem. We expect most of the cases this will succeed.
            token = FileUtils.readFileToString(tokenFile.toFile(), Charset.defaultCharset());
            DecodedJWT decoded = jwtController.verifyToken(token, settings.getJWTIssuer());
            airflowJWT = new AirflowJWT(user.getUsername(), project.getId(), project.getName(), DateUtils.date2LocalDateTime(decoded.getExpiresAt()), user.getUid());
            airflowJWT.tokenFile = tokenFile;
            airflowJWT.token = token;
            LOG.log(Level.FINE, "Successfully read existing JWT from local filesystem for " + materialIdentifier);
        } catch (IOException | JWTException | JWTDecodeException ex) {
            // JWT does not exist in the filesystem or we cannot read them or it is not valid any longer
            // We will create a new one
            // TODO(Antonis): Not very good that audience is hardcoded, but it is not accessible from hopsworks-common
            String[] audience = new String[] { "api" };
            LocalDateTime expirationDate = DateUtils.getNow().plus(settings.getJWTLifetimeMs(), ChronoUnit.MILLIS);
            String[] roles = getUserRoles(user);
            try {
                LOG.log(Level.FINEST, "JWT for " + materialIdentifier + " does not exist in the local FS or it is not " + "valid any longer, creating new one...");
                Map<String, Object> claims = new HashMap<>(3);
                claims.put(Constants.RENEWABLE, false);
                claims.put(Constants.EXPIRY_LEEWAY, settings.getJWTExpLeewaySec());
                claims.put(Constants.ROLES, roles);
                token = jwtController.createToken(settings.getJWTSigningKeyName(), false, settings.getJWTIssuer(), audience, DateUtils.localDateTime2Date(expirationDate), DateUtils.localDateTime2Date(DateUtils.getNow()), user.getUsername(), claims, SignatureAlgorithm.valueOf(settings.getJWTSignatureAlg()));
                airflowJWT = new AirflowJWT(user.getUsername(), project.getId(), project.getName(), expirationDate, user.getUid());
                airflowJWT.tokenFile = tokenFile;
                airflowJWT.token = token;
                writeTokenToFile(airflowJWT);
                LOG.log(Level.FINE, "Created new JWT for " + materialIdentifier + " and flushed to local FS");
            } catch (IOException ex1) {
                // Managed to create token but failed to write
                LOG.log(Level.WARNING, "Could not write to local FS new JWT for recovered material " + materialIdentifier + ". We will invalidate it and won't renew it.", ex1);
                if (token != null) {
                    try {
                        LOG.log(Level.FINE, "Failed to write JWT for " + materialIdentifier + ". Invalidating it...");
                        jwtController.invalidate(token);
                    } catch (InvalidationException ex2) {
                    // Not much we can do about it
                    }
                }
                failed2recover.add(material);
                continue;
            } catch (GeneralSecurityException | JWTException ex1) {
                LOG.log(Level.WARNING, "Tried to recover JWT for " + materialIdentifier + " but we failed. Giving up... " + "JWT will not be available for Airflow DAGs", ex1);
                // Initial token is invalid and could not create new. Give up
                failed2recover.add(material);
                continue;
            }
        }
        // If everything went fine with JWT, proceed with X.509
        try {
            LOG.log(Level.FINEST, "Materializing X.509 for " + materialIdentifier);
            certificateMaterializer.materializeCertificatesLocalCustomDir(user.getUsername(), project.getName(), getProjectSecretsDirectory(user.getUsername()).toString());
            LOG.log(Level.FINE, "Materialized X.509 for " + materialIdentifier);
            airflowJWTs.add(airflowJWT);
        } catch (IOException ex) {
            LOG.log(Level.WARNING, "Could not materialize X.509 for " + materialIdentifier + " Invalidating JWT and deleting from FS. JWT and X.509 will not be available for Airflow DAGs.", ex);
            // Could not materialize X.509
            if (token != null) {
                try {
                    LOG.log(Level.FINE, "Failed to materialize X.509 for " + materialIdentifier + " Invalidating JWT and deleting it from local FS.");
                    jwtController.invalidate(token);
                    FileUtils.deleteDirectory(getProjectSecretsDirectory(user.getUsername()).toFile());
                } catch (InvalidationException | IOException ex1) {
                // Not much we can do about it
                }
            }
            failed2recover.add(material);
        }
    }
    // Remove failed material from persistent storage
    for (MaterializedJWT failed : failed2recover) {
        materializedJWTFacade.delete(failed.getIdentifier());
    }
}
Also used : Path(java.nio.file.Path) LocalDateTime(java.time.LocalDateTime) JWTException(io.hops.hopsworks.jwt.exception.JWTException) ArrayList(java.util.ArrayList) Users(io.hops.hopsworks.persistence.entity.user.Users) IOException(java.io.IOException) MaterializedJWT(io.hops.hopsworks.persistence.entity.airflow.MaterializedJWT) Project(io.hops.hopsworks.persistence.entity.project.Project) JWTDecodeException(com.auth0.jwt.exceptions.JWTDecodeException) InvalidationException(io.hops.hopsworks.jwt.exception.InvalidationException) DecodedJWT(com.auth0.jwt.interfaces.DecodedJWT) Map(java.util.Map) HashMap(java.util.HashMap)

Example 8 with InvalidationException

use of io.hops.hopsworks.jwt.exception.InvalidationException in project hopsworks by logicalclocks.

the class JupyterJWTManager method materializeJWT.

@Lock(LockType.WRITE)
@AccessTimeout(value = 2000)
public void materializeJWT(Users user, Project project, JupyterSettings jupyterSettings, String cid, Integer port, String[] audience) throws ServiceException {
    MaterializedJWTID materialID = new MaterializedJWTID(project.getId(), user.getUid(), MaterializedJWTID.USAGE.JUPYTER);
    if (!materializedJWTFacade.exists(materialID)) {
        LocalDateTime expirationDate = LocalDateTime.now().plus(settings.getJWTLifetimeMs(), ChronoUnit.MILLIS);
        JupyterJWT jupyterJWT = new JupyterJWT(project, user, expirationDate, new CidAndPort(cid, port));
        try {
            String[] roles = usersController.getUserRoles(user).toArray(new String[1]);
            MaterializedJWT materializedJWT = new MaterializedJWT(materialID);
            materializedJWTFacade.persist(materializedJWT);
            Map<String, Object> claims = new HashMap<>(3);
            claims.put(Constants.RENEWABLE, false);
            claims.put(Constants.EXPIRY_LEEWAY, settings.getJWTExpLeewaySec());
            claims.put(Constants.ROLES, roles);
            String token = jwtController.createToken(settings.getJWTSigningKeyName(), false, settings.getJWTIssuer(), audience, DateUtils.localDateTime2Date(expirationDate), DateUtils.localDateTime2Date(DateUtils.getNow()), user.getUsername(), claims, SignatureAlgorithm.valueOf(settings.getJWTSignatureAlg()));
            jupyterJWT.tokenFile = constructTokenFilePath(jupyterSettings);
            jupyterJWT.token = token;
            jwtTokenWriter.writeToken(settings, jupyterJWT);
            addToken(jupyterJWT);
        } catch (GeneralSecurityException | JWTException ex) {
            LOG.log(Level.SEVERE, "Error generating Jupyter JWT for " + jupyterJWT, ex);
            materializedJWTFacade.delete(materialID);
            throw new ServiceException(RESTCodes.ServiceErrorCode.JUPYTER_START_ERROR, Level.SEVERE, "Could not generate Jupyter JWT", ex.getMessage(), ex);
        } catch (IOException ex) {
            LOG.log(Level.SEVERE, "Error writing Jupyter JWT to file for " + jupyterJWT, ex);
            materializedJWTFacade.delete(materialID);
            try {
                jwtController.invalidate(jupyterJWT.token);
            } catch (InvalidationException invEx) {
                LOG.log(Level.FINE, "Could not invalidate Jupyter JWT after failure to write to file", ex);
            }
            throw new ServiceException(RESTCodes.ServiceErrorCode.JUPYTER_START_ERROR, Level.SEVERE, "Could not write Jupyter JWT to file", ex.getMessage(), ex);
        }
    }
}
Also used : LocalDateTime(java.time.LocalDateTime) HashMap(java.util.HashMap) JWTException(io.hops.hopsworks.jwt.exception.JWTException) GeneralSecurityException(java.security.GeneralSecurityException) IOException(java.io.IOException) MaterializedJWT(io.hops.hopsworks.persistence.entity.airflow.MaterializedJWT) MaterializedJWTID(io.hops.hopsworks.persistence.entity.airflow.MaterializedJWTID) ServiceException(io.hops.hopsworks.exceptions.ServiceException) InvalidationException(io.hops.hopsworks.jwt.exception.InvalidationException) AccessTimeout(javax.ejb.AccessTimeout) Lock(javax.ejb.Lock)

Example 9 with InvalidationException

use of io.hops.hopsworks.jwt.exception.InvalidationException in project hopsworks by logicalclocks.

the class JWTController method invalidate.

/**
 * Invalidate a token by adding it to the invalid tokens table.
 *
 * @param token
 * @throws io.hops.hopsworks.jwt.exception.InvalidationException
 */
public void invalidate(String token) throws InvalidationException {
    if (token == null || token.isEmpty()) {
        return;
    }
    DecodedJWT jwt;
    try {
        jwt = verifyToken(token, null);
    } catch (Exception ex) {
        // no need to invalidate if not valid
        return;
    }
    int expLeeway = getExpLeewayClaim(jwt);
    invalidateJWT(jwt.getId(), jwt.getExpiresAt(), expLeeway);
}
Also used : DecodedJWT(com.auth0.jwt.interfaces.DecodedJWT) NotRenewableException(io.hops.hopsworks.jwt.exception.NotRenewableException) DuplicateSigningKeyException(io.hops.hopsworks.jwt.exception.DuplicateSigningKeyException) AccessLocalException(javax.ejb.AccessLocalException) SigningKeyNotFoundException(io.hops.hopsworks.jwt.exception.SigningKeyNotFoundException) JWTException(io.hops.hopsworks.jwt.exception.JWTException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) VerificationException(io.hops.hopsworks.jwt.exception.VerificationException) InvalidationException(io.hops.hopsworks.jwt.exception.InvalidationException)

Example 10 with InvalidationException

use of io.hops.hopsworks.jwt.exception.InvalidationException in project hopsworks by logicalclocks.

the class JWTController method invalidateJWT.

private void invalidateJWT(String id, Date exp, int leeway) throws InvalidationException {
    try {
        InvalidJwt invalidJwt = new InvalidJwt(id, exp, leeway);
        invalidJwtFacade.persist(invalidJwt);
    } catch (Exception e) {
        throw new InvalidationException("Could not persist token.", e.getCause());
    }
}
Also used : InvalidJwt(io.hops.hopsworks.persistence.entity.jwt.InvalidJwt) InvalidationException(io.hops.hopsworks.jwt.exception.InvalidationException) NotRenewableException(io.hops.hopsworks.jwt.exception.NotRenewableException) DuplicateSigningKeyException(io.hops.hopsworks.jwt.exception.DuplicateSigningKeyException) AccessLocalException(javax.ejb.AccessLocalException) SigningKeyNotFoundException(io.hops.hopsworks.jwt.exception.SigningKeyNotFoundException) JWTException(io.hops.hopsworks.jwt.exception.JWTException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) VerificationException(io.hops.hopsworks.jwt.exception.VerificationException) InvalidationException(io.hops.hopsworks.jwt.exception.InvalidationException)

Aggregations

InvalidationException (io.hops.hopsworks.jwt.exception.InvalidationException)10 JWTException (io.hops.hopsworks.jwt.exception.JWTException)8 IOException (java.io.IOException)6 LocalDateTime (java.time.LocalDateTime)6 HashMap (java.util.HashMap)5 JWTDecodeException (com.auth0.jwt.exceptions.JWTDecodeException)4 DecodedJWT (com.auth0.jwt.interfaces.DecodedJWT)4 MaterializedJWT (io.hops.hopsworks.persistence.entity.airflow.MaterializedJWT)4 GeneralSecurityException (java.security.GeneralSecurityException)4 AccessTimeout (javax.ejb.AccessTimeout)4 Lock (javax.ejb.Lock)4 Users (io.hops.hopsworks.persistence.entity.user.Users)3 AirflowException (io.hops.hopsworks.exceptions.AirflowException)2 ServiceException (io.hops.hopsworks.exceptions.ServiceException)2 DuplicateSigningKeyException (io.hops.hopsworks.jwt.exception.DuplicateSigningKeyException)2 NotRenewableException (io.hops.hopsworks.jwt.exception.NotRenewableException)2 SigningKeyNotFoundException (io.hops.hopsworks.jwt.exception.SigningKeyNotFoundException)2 VerificationException (io.hops.hopsworks.jwt.exception.VerificationException)2 MaterializedJWTID (io.hops.hopsworks.persistence.entity.airflow.MaterializedJWTID)2 Project (io.hops.hopsworks.persistence.entity.project.Project)2