Add extra workspace existence check before creating keypair

6.19.x
Max Shaposhnik 2018-09-19 16:59:22 +03:00 committed by GitHub
parent 0ec95375e0
commit f838ea5a60
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 178 additions and 203 deletions

View File

@ -43,7 +43,6 @@ import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Named;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.core.model.workspace.config.MachineConfig;
import org.eclipse.che.api.core.model.workspace.config.ServerConfig;
import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
@ -52,6 +51,7 @@ import org.eclipse.che.api.workspace.server.spi.InternalInfrastructureException;
import org.eclipse.che.api.workspace.server.spi.environment.InternalMachineConfig;
import org.eclipse.che.commons.lang.Size;
import org.eclipse.che.multiuser.machine.authentication.server.signature.SignatureKeyManager;
import org.eclipse.che.multiuser.machine.authentication.server.signature.SignatureKeyManagerException;
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
import org.eclipse.che.workspace.infrastructure.kubernetes.server.ServerServiceBuilder;
import org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.jwtproxy.factory.JwtProxyConfigBuilderFactory;
@ -211,8 +211,8 @@ public class JwtProxyProvisioner {
KeyPair keyPair;
try {
keyPair = signatureKeyManager.getKeyPair(identity.getWorkspaceId());
} catch (ServerException e) {
keyPair = signatureKeyManager.getOrCreateKeyPair(identity.getWorkspaceId());
} catch (SignatureKeyManagerException e) {
throw new InternalInfrastructureException(
"Signature key pair for machine authentication cannot be retrieved. Reason: "
+ e.getMessage());

View File

@ -75,7 +75,8 @@ public class JwtProxyProvisionerTest {
@BeforeMethod
public void setUp() throws Exception {
when(signatureKeyManager.getKeyPair(anyString())).thenReturn(new KeyPair(publicKey, null));
when(signatureKeyManager.getOrCreateKeyPair(anyString()))
.thenReturn(new KeyPair(publicKey, null));
when(publicKey.getEncoded()).thenReturn("publickey".getBytes());
when(configBuilderFactory.create(any()))

View File

@ -85,7 +85,7 @@ public class KeycloakEnvironmentInitalizationFilterTest {
parser.setAccessible(true);
parser.set(filter, jwtParser);
final KeyPair kp = new KeyPair(mock(PublicKey.class), mock(PrivateKey.class));
when(keyManager.getKeyPair(anyString())).thenReturn(kp);
when(keyManager.getOrCreateKeyPair(anyString())).thenReturn(kp);
}
@Test

View File

@ -90,10 +90,6 @@
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-workspace-shared</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-commons-annotations</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-commons-auth</artifactId>

View File

@ -43,6 +43,8 @@ import org.eclipse.che.commons.env.EnvironmentContext;
import org.eclipse.che.commons.subject.Subject;
import org.eclipse.che.commons.subject.SubjectImpl;
import org.eclipse.che.multiuser.api.permission.server.PermissionChecker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Handles requests that comes from machines with specific machine token.
@ -53,6 +55,8 @@ import org.eclipse.che.multiuser.api.permission.server.PermissionChecker;
@Singleton
public class MachineLoginFilter implements Filter {
private static final Logger LOG = LoggerFactory.getLogger(MachineLoginFilter.class);
private final RequestTokenExtractor tokenExtractor;
private final UserManager userManager;
private final PermissionChecker permissionChecker;

View File

@ -21,8 +21,8 @@ import io.jsonwebtoken.SigningKeyResolverAdapter;
import java.security.Key;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.multiuser.machine.authentication.server.signature.SignatureKeyManager;
import org.eclipse.che.multiuser.machine.authentication.server.signature.SignatureKeyManagerException;
/** Resolves signing key pair based on workspace Id claim of token. */
@Singleton
@ -46,9 +46,9 @@ public class MachineSigningKeyResolver extends SigningKeyResolverAdapter {
"Unable to fetch signature key pair: no workspace id present in token");
}
try {
return keyManager.getKeyPair(wsId).getPublic();
} catch (ServerException e) {
throw new JwtException("Unable to fetch signature key pair:" + e.getMessage());
return keyManager.getOrCreateKeyPair(wsId).getPublic();
} catch (SignatureKeyManagerException e) {
throw new JwtException("Unable to fetch signature key pair:" + e.getMessage(), e);
}
}
}

View File

@ -33,7 +33,9 @@ import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.core.model.user.User;
import org.eclipse.che.api.user.server.UserManager;
import org.eclipse.che.api.workspace.server.token.MachineTokenException;
import org.eclipse.che.multiuser.machine.authentication.server.signature.SignatureKeyManager;
import org.eclipse.che.multiuser.machine.authentication.server.signature.SignatureKeyManagerException;
import org.eclipse.che.multiuser.machine.authentication.shared.Constants;
/**
@ -66,9 +68,9 @@ public class MachineTokenRegistry {
* @param userId id of user to get token
* @param workspaceId id of workspace to get token
* @return machine security token for for given user and workspace
* @throws IllegalStateException when user with given id not found or any errors occurs
* @throws MachineTokenException when user with given id not found or any errors occurs
*/
public String getOrCreateToken(String userId, String workspaceId) {
public String getOrCreateToken(String userId, String workspaceId) throws MachineTokenException {
lock.writeLock().lock();
try {
final Map<String, String> wsRow = tokens.row(workspaceId);
@ -77,41 +79,43 @@ public class MachineTokenRegistry {
token = createToken(userId, workspaceId);
}
return token;
} catch (NotFoundException | ServerException ex) {
throw new IllegalStateException(
format(
"Failed to generate machine token for user '%s' and workspace '%s'. Cause: '%s'",
userId, workspaceId, ex.getMessage()),
ex);
} finally {
lock.writeLock().unlock();
}
}
/** Creates new token with given data. */
private String createToken(String userId, String workspaceId)
throws NotFoundException, ServerException {
final PrivateKey privateKey = signatureKeyManager.getKeyPair(workspaceId).getPrivate();
final User user = userManager.getById(userId);
final Map<String, Object> header = new HashMap<>(2);
header.put("kind", MACHINE_TOKEN_KIND);
header.put("kid", workspaceId);
final Map<String, Object> claims = new HashMap<>();
// to ensure that each token is unique
claims.put(Claims.ID, UUID.randomUUID().toString());
claims.put(Constants.USER_ID_CLAIM, userId);
claims.put(Constants.USER_NAME_CLAIM, user.getName());
claims.put(Constants.WORKSPACE_ID_CLAIM, workspaceId);
// jwtproxy required claims
claims.put(Claims.ISSUER, "wsmaster");
claims.put(Claims.AUDIENCE, workspaceId);
claims.put(Claims.EXPIRATION, Instant.now().plus(365, DAYS).getEpochSecond());
claims.put(Claims.NOT_BEFORE, -1); // always
claims.put(Claims.ISSUED_AT, Instant.now().getEpochSecond());
final String token =
Jwts.builder().setClaims(claims).setHeader(header).signWith(RS256, privateKey).compact();
tokens.put(workspaceId, userId, token);
return token;
private String createToken(String userId, String workspaceId) throws MachineTokenException {
try {
final PrivateKey privateKey =
signatureKeyManager.getOrCreateKeyPair(workspaceId).getPrivate();
final User user = userManager.getById(userId);
final Map<String, Object> header = new HashMap<>(2);
header.put("kind", MACHINE_TOKEN_KIND);
header.put("kid", workspaceId);
final Map<String, Object> claims = new HashMap<>();
// to ensure that each token is unique
claims.put(Claims.ID, UUID.randomUUID().toString());
claims.put(Constants.USER_ID_CLAIM, userId);
claims.put(Constants.USER_NAME_CLAIM, user.getName());
claims.put(Constants.WORKSPACE_ID_CLAIM, workspaceId);
// jwtproxy required claims
claims.put(Claims.ISSUER, "wsmaster");
claims.put(Claims.AUDIENCE, workspaceId);
claims.put(Claims.EXPIRATION, Instant.now().plus(365, DAYS).getEpochSecond());
claims.put(Claims.NOT_BEFORE, -1); // always
claims.put(Claims.ISSUED_AT, Instant.now().getEpochSecond());
final String token =
Jwts.builder().setClaims(claims).setHeader(header).signWith(RS256, privateKey).compact();
tokens.put(workspaceId, userId, token);
return token;
} catch (SignatureKeyManagerException | NotFoundException | ServerException ex) {
throw new MachineTokenException(
format(
"Failed to generate machine token for user '%s' and workspace '%s'. Cause: '%s'",
userId, workspaceId, ex.getMessage()),
ex);
}
}
/**

View File

@ -15,9 +15,6 @@ import static org.eclipse.che.api.core.model.workspace.WorkspaceStatus.STOPPED;
import com.google.common.annotations.Beta;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
@ -28,8 +25,6 @@ import java.security.spec.EncodedKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.inject.Named;
@ -40,7 +35,6 @@ import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.core.notification.EventService;
import org.eclipse.che.api.core.notification.EventSubscriber;
import org.eclipse.che.api.workspace.shared.dto.event.WorkspaceStatusEvent;
import org.eclipse.che.commons.annotation.Nullable;
import org.eclipse.che.core.db.DBInitializer;
import org.eclipse.che.multiuser.machine.authentication.server.signature.model.impl.SignatureKeyPairImpl;
import org.eclipse.che.multiuser.machine.authentication.server.signature.spi.SignatureKeyDao;
@ -72,8 +66,6 @@ public class SignatureKeyManager {
@SuppressWarnings("unused")
private DBInitializer dbInitializer;
private LoadingCache<String, KeyPair> cachedPair;
@Inject
public SignatureKeyManager(
@Named("che.auth.signature_key_size") int keySize,
@ -84,19 +76,6 @@ public class SignatureKeyManager {
this.algorithm = algorithm;
this.eventService = eventService;
this.signatureKeyDao = signatureKeyDao;
this.cachedPair =
CacheBuilder.newBuilder()
.maximumSize(100)
.expireAfterAccess(2, TimeUnit.HOURS)
.build(
new CacheLoader<String, KeyPair>() {
@Override
public KeyPair load(String key) throws Exception {
return loadKeyPair(key);
}
});
this.workspaceEventsSubscriber =
new EventSubscriber<WorkspaceStatusEvent>() {
@Override
@ -108,21 +87,34 @@ public class SignatureKeyManager {
};
}
/** Returns cached instance of {@link KeyPair} or null when failed to load key pair. */
@Nullable
public KeyPair getKeyPair(String workspaceId) throws ServerException {
/**
* Returns instance of {@link KeyPair} for given workspace.
*
* @throws SignatureKeyManagerException when stored keypair is incorrect (e.g. has bad algorithm
* or keyspec) or other error
*/
public KeyPair getOrCreateKeyPair(String workspaceId) throws SignatureKeyManagerException {
SignatureKeyPair keyPair;
try {
return cachedPair.get(workspaceId);
} catch (ExecutionException e) {
throw new ServerException(e.getCause());
try {
keyPair = signatureKeyDao.get(workspaceId);
} catch (NotFoundException e) {
keyPair = generateKeyPair(workspaceId);
}
} catch (NoSuchAlgorithmException | ServerException | ConflictException ex) {
LOG.error(
"Failed to load signature keys for ws {}. Cause: {}", workspaceId, ex.getMessage());
throw new SignatureKeyManagerException(ex.getMessage(), ex);
}
return toJavaKeyPair(keyPair);
}
/** Removes key pair from cache and DB. */
public void removeKeyPair(String workspaceId) {
@VisibleForTesting
void removeKeyPair(String workspaceId) {
try {
cachedPair.invalidate(workspaceId);
signatureKeyDao.remove(workspaceId);
LOG.debug("Removed signature key pair for ws id {}.", workspaceId);
} catch (ServerException e) {
LOG.error(
"Unable to cleanup machine token signature keypairs for ws {}. Cause: {}",
@ -131,64 +123,31 @@ public class SignatureKeyManager {
}
}
/** Loads signature key pair if no existing keys found then stores a newly generated key pair. */
@PostConstruct
@VisibleForTesting
KeyPair loadKeyPair(String workspaceId) throws ServerException, ConflictException {
SignatureKeyPair generateKeyPair(String workspaceId)
throws NoSuchAlgorithmException, ServerException, ConflictException {
try {
return toJavaKeyPair(signatureKeyDao.get(workspaceId));
} catch (NotFoundException nfe) {
try {
return toJavaKeyPair(signatureKeyDao.create(generateKeyPair(workspaceId)));
} catch (ConflictException | ServerException ex) {
LOG.error(
"Failed to store signature keys for ws {}. Cause: {}", workspaceId, ex.getMessage());
throw ex;
}
} catch (ServerException ex) {
KeyPairGenerator kpg = KeyPairGenerator.getInstance(algorithm);
kpg.initialize(keySize);
final KeyPair pair = kpg.generateKeyPair();
final SignatureKeyPairImpl kp =
new SignatureKeyPairImpl(workspaceId, pair.getPublic(), pair.getPrivate());
LOG.debug(
"Generated signature key pair with ws id {} and algorithm {}.",
kp.getWorkspaceId(),
algorithm);
return signatureKeyDao.create(kp);
} catch (NoSuchAlgorithmException | ConflictException | ServerException ex) {
LOG.error(
"Failed to load signature keys for ws {}. Cause: {}", workspaceId, ex.getMessage());
"Unable to generate signature keypair for ws {}. Cause: {}",
workspaceId,
ex.getMessage());
throw ex;
}
}
@VisibleForTesting
SignatureKeyPairImpl generateKeyPair(String workspaceId) throws ServerException {
final KeyPairGenerator kpg;
try {
kpg = KeyPairGenerator.getInstance(algorithm);
} catch (NoSuchAlgorithmException ex) {
throw new ServerException(ex.getMessage(), ex);
}
kpg.initialize(keySize);
final KeyPair pair = kpg.generateKeyPair();
final SignatureKeyPairImpl kp =
new SignatureKeyPairImpl(workspaceId, pair.getPublic(), pair.getPrivate());
LOG.debug(
"Generated signature key pair with ws id {} and algorithm {}.",
kp.getWorkspaceId(),
algorithm);
return kp;
}
/** Converts {@link SignatureKeyPair} to {@link KeyPair}. */
public static KeyPair toJavaKeyPair(SignatureKeyPair keyPair) throws ServerException {
try {
final PrivateKey privateKey =
KeyFactory.getInstance(keyPair.getPrivateKey().getAlgorithm())
.generatePrivate(getKeySpec(keyPair.getPrivateKey()));
final PublicKey publicKey =
KeyFactory.getInstance(keyPair.getPublicKey().getAlgorithm())
.generatePublic(getKeySpec(keyPair.getPublicKey()));
return new KeyPair(publicKey, privateKey);
} catch (NoSuchAlgorithmException | InvalidKeySpecException ex) {
LOG.error("Failed to convert signature key pair to Java keys. Cause: {}", ex.getMessage());
throw new ServerException("Failed to convert signature key pair to Java keys.");
}
}
/** Returns key spec by key format and encoded data. */
private static EncodedKeySpec getKeySpec(SignatureKey key) {
private EncodedKeySpec getKeySpec(SignatureKey key) {
switch (key.getFormat()) {
case PKCS_8:
return new PKCS8EncodedKeySpec(key.getEncoded());
@ -200,6 +159,21 @@ public class SignatureKeyManager {
}
}
private KeyPair toJavaKeyPair(SignatureKeyPair keyPair) throws SignatureKeyManagerException {
try {
final PrivateKey privateKey =
KeyFactory.getInstance(keyPair.getPrivateKey().getAlgorithm())
.generatePrivate(getKeySpec(keyPair.getPrivateKey()));
final PublicKey publicKey =
KeyFactory.getInstance(keyPair.getPublicKey().getAlgorithm())
.generatePublic(getKeySpec(keyPair.getPublicKey()));
return new KeyPair(publicKey, privateKey);
} catch (NoSuchAlgorithmException | InvalidKeySpecException ex) {
LOG.error("Failed to convert signature key pair to Java keys. Cause: {}", ex.getMessage());
throw new SignatureKeyManagerException("Failed to convert signature key pair to Java keys.");
}
}
@VisibleForTesting
@PostConstruct
void subscribe() {

View File

@ -0,0 +1,22 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.multiuser.machine.authentication.server.signature;
public class SignatureKeyManagerException extends Exception {
public SignatureKeyManagerException(String message) {
super(message);
}
public SignatureKeyManagerException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -15,7 +15,6 @@ import static org.eclipse.che.multiuser.machine.authentication.shared.Constants.
import java.util.Base64;
import javax.inject.Inject;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
import org.eclipse.che.api.workspace.server.spi.provision.env.EnvVarProvider;
@ -44,10 +43,10 @@ public class SignaturePublicKeyEnvProvider implements EnvVarProvider {
Base64.getEncoder()
.encode(
keyManager
.getKeyPair(runtimeIdentity.getWorkspaceId())
.getOrCreateKeyPair(runtimeIdentity.getWorkspaceId())
.getPublic()
.getEncoded())));
} catch (ServerException e) {
} catch (SignatureKeyManagerException e) {
throw new InfrastructureException(
"Signature key pair for machine authentication cannot be retrieved. Reason: "
+ e.getMessage());

View File

@ -29,6 +29,7 @@ import org.eclipse.che.api.core.notification.EventService;
import org.eclipse.che.api.workspace.server.event.BeforeWorkspaceRemovedEvent;
import org.eclipse.che.core.db.cascade.CascadeEventSubscriber;
import org.eclipse.che.core.db.jpa.DuplicateKeyException;
import org.eclipse.che.core.db.jpa.IntegrityConstraintViolationException;
import org.eclipse.che.multiuser.machine.authentication.server.signature.model.impl.SignatureKeyPairImpl;
import org.eclipse.che.multiuser.machine.authentication.server.signature.spi.SignatureKeyDao;
@ -53,6 +54,12 @@ public class JpaSignatureKeyDao implements SignatureKeyDao {
requireNonNull(keyPair, "Required non-null key pair");
try {
doCreate(keyPair);
} catch (IntegrityConstraintViolationException x) {
throw new ConflictException(
format(
"Unable to create signature key pair because referenced workspace with id '%s' doesn't exist",
keyPair.getWorkspaceId()));
} catch (DuplicateKeyException dkEx) {
throw new ConflictException(
format("Signature key pair for workspace '%s' already exists", keyPair.getWorkspaceId()));

View File

@ -107,7 +107,7 @@ public class MachineLoginFilterTest {
permissionCheckerMock);
when(tokenExtractorMock.getToken(any(HttpServletRequest.class))).thenReturn(token);
when(keyManagerMock.getKeyPair(eq(WORKSPACE_ID))).thenReturn(keyPair);
when(keyManagerMock.getOrCreateKeyPair(eq(WORKSPACE_ID))).thenReturn(keyPair);
when(userMock.getName()).thenReturn(SUBJECT.getUserName());
when(userManagerMock.getById(SUBJECT.getUserId())).thenReturn(userMock);
@ -117,7 +117,7 @@ public class MachineLoginFilterTest {
public void testProcessRequestWithValidToken() throws Exception {
machineLoginFilter.doFilter(getRequestMock(), responseMock, chainMock);
verify(keyManagerMock).getKeyPair(eq(WORKSPACE_ID));
verify(keyManagerMock).getOrCreateKeyPair(eq(WORKSPACE_ID));
verify(userManagerMock).getById(anyString());
verifyZeroInteractions(responseMock);
}
@ -128,7 +128,7 @@ public class MachineLoginFilterTest {
final KeyPairGenerator kpg = KeyPairGenerator.getInstance(SIGNATURE_ALGORITHM);
kpg.initialize(KEY_SIZE);
final KeyPair pair = kpg.generateKeyPair();
when(keyManagerMock.getKeyPair(eq(WORKSPACE_ID))).thenReturn(pair);
when(keyManagerMock.getOrCreateKeyPair(eq(WORKSPACE_ID))).thenReturn(pair);
machineLoginFilter.doFilter(requestMock, responseMock, chainMock);
@ -186,7 +186,7 @@ public class MachineLoginFilterTest {
machineLoginFilter.doFilter(getRequestMock(), responseMock, chainMock);
verify(keyManagerMock).getKeyPair(eq(WORKSPACE_ID));
verify(keyManagerMock).getOrCreateKeyPair(eq(WORKSPACE_ID));
verify(userManagerMock).getById(anyString());
verify(responseMock)
.sendError(
@ -200,7 +200,7 @@ public class MachineLoginFilterTest {
machineLoginFilter.doFilter(getRequestMock(), responseMock, chainMock);
verify(keyManagerMock).getKeyPair(eq(WORKSPACE_ID));
verify(keyManagerMock).getOrCreateKeyPair(eq(WORKSPACE_ID));
verify(userManagerMock).getById(anyString());
verify(responseMock)
.sendError(

View File

@ -31,6 +31,8 @@ import java.util.Map;
import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.model.user.User;
import org.eclipse.che.api.user.server.UserManager;
import org.eclipse.che.api.workspace.server.WorkspaceManager;
import org.eclipse.che.api.workspace.server.token.MachineTokenException;
import org.eclipse.che.commons.subject.SubjectImpl;
import org.eclipse.che.multiuser.machine.authentication.server.signature.SignatureKeyManager;
import org.mockito.Mock;
@ -58,6 +60,7 @@ public class MachineTokenRegistryTest {
@Mock private SignatureKeyManager signatureKeyManager;
@Mock private UserManager userManager;
@Mock private WorkspaceManager workspaceManager;
private KeyPair keyPair;
@ -69,7 +72,7 @@ public class MachineTokenRegistryTest {
keyPair = kpg.generateKeyPair();
mockUser(USER_ID, USER_NAME);
when(signatureKeyManager.getKeyPair(anyString())).thenReturn(keyPair);
when(signatureKeyManager.getOrCreateKeyPair(anyString())).thenReturn(keyPair);
}
@Test
@ -89,11 +92,11 @@ public class MachineTokenRegistryTest {
assertEquals(subject.getUserName(), USER_NAME);
assertEquals(claims.get(WORKSPACE_ID_CLAIM, String.class), WORKSPACE_ID);
verify(userManager).getById(USER_ID);
verify(signatureKeyManager).getKeyPair(anyString());
verify(signatureKeyManager).getOrCreateKeyPair(anyString());
assertNotNull(generatedToken);
}
@Test(expectedExceptions = IllegalStateException.class)
@Test(expectedExceptions = MachineTokenException.class)
public void testThrowsIllegalStateExceptionWhenTryToGetTokenForNonExistingUser()
throws Exception {
when(userManager.getById(anyString())).thenThrow(new NotFoundException("User not found"));

View File

@ -11,11 +11,9 @@
*/
package org.eclipse.che.multiuser.machine.authentication.server.signature;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@ -25,8 +23,6 @@ import static org.testng.Assert.assertNotNull;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.core.model.workspace.WorkspaceStatus;
import org.eclipse.che.api.core.notification.EventService;
import org.eclipse.che.api.core.notification.EventSubscriber;
@ -38,7 +34,6 @@ import org.eclipse.che.multiuser.machine.authentication.server.signature.spi.Sig
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.stubbing.Answer;
import org.mockito.testng.MockitoTestNGListener;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Listeners;
@ -71,70 +66,6 @@ public class SignatureKeyManagerTest {
new SignatureKeyManager(KEY_SIZE, ALGORITHM, eventService, signatureKeyDao);
}
@Test
public void testLoadSignatureKeys() throws Exception {
String wsId = "WS_id_1";
final SignatureKeyPairImpl kp = newKeyPair(wsId);
when(signatureKeyDao.get(anyString())).thenReturn(kp);
signatureKeyManager.loadKeyPair(wsId);
final KeyPair cachedPair = signatureKeyManager.getKeyPair(wsId);
assertNotNull(cachedPair);
assertKeys(cachedPair.getPublic(), kp.getPublicKey());
assertKeys(cachedPair.getPrivate(), kp.getPrivateKey());
}
@Test
public void testTriesToLoadKeysOnGettingKeyPairAndNoCachedKeyPair() throws Exception {
String wsId = "WS_id_1";
final SignatureKeyPairImpl kp = newKeyPair(wsId);
when(signatureKeyDao.create(any(SignatureKeyPairImpl.class))).thenReturn(kp);
when(signatureKeyDao.get(anyString())).thenThrow(new NotFoundException("not found"));
signatureKeyManager.getKeyPair("ws1");
verify(signatureKeyDao).get(anyString());
verify(signatureKeyDao).create(any(SignatureKeyPairImpl.class));
}
@Test
public void testGeneratesNewKeyPairWhenNoExistingKeyPairFound() throws Exception {
doThrow(NotFoundException.class).when(signatureKeyDao).get(anyString());
when(signatureKeyDao.create(any(SignatureKeyPairImpl.class)))
.thenAnswer((Answer<SignatureKeyPairImpl>) invoke -> invoke.getArgument(0));
final KeyPair cachedPair = signatureKeyManager.getKeyPair("ws1");
verify(signatureKeyDao).get(anyString());
verify(signatureKeyDao).create(any(SignatureKeyPairImpl.class));
assertNotNull(cachedPair);
}
@Test(expectedExceptions = ServerException.class)
public void testThrowsExceptionWhenFailedToLoadAndGenerateKeys() throws Exception {
doThrow(NotFoundException.class).when(signatureKeyDao).get(anyString());
when(signatureKeyDao.create(any(SignatureKeyPairImpl.class)))
.thenThrow(new ServerException("unexpected end of stack"));
signatureKeyManager.getKeyPair("ws1");
verify(signatureKeyDao).get(anyString());
verify(signatureKeyDao).create(any(SignatureKeyPairImpl.class));
}
@Test(expectedExceptions = ServerException.class)
public void testThrowsExceptionWhenAlgorithmIsNotSupported() throws Exception {
final SignatureKeyImpl publicKey = new SignatureKeyImpl(new byte[] {}, "ECDH", "PKCS#15");
final SignatureKeyImpl privateKey = new SignatureKeyImpl(new byte[] {}, "ECDH", "PKCS#3");
final SignatureKeyPairImpl kp = new SignatureKeyPairImpl("id_" + 1, publicKey, privateKey);
doReturn(kp).when(signatureKeyDao).get(anyString());
signatureKeyManager.getKeyPair("ws1");
verify(signatureKeyDao).get(anyString());
}
@Test
public void shouldRemoveKeyPairOnWorkspaceStop() throws Exception {
final String wsId = "ws123";
@ -150,6 +81,31 @@ public class SignatureKeyManagerTest {
verify(signatureKeyDao, times(1)).remove(eq(wsId));
}
@Test(expectedExceptions = SignatureKeyManagerException.class)
public void shouldThrowsExceptionWhenAlgorithmIsNotSupported() throws Exception {
final SignatureKeyImpl publicKey = new SignatureKeyImpl(new byte[] {}, "ECDH", "PKCS#15");
final SignatureKeyImpl privateKey = new SignatureKeyImpl(new byte[] {}, "ECDH", "PKCS#3");
final SignatureKeyPairImpl kp = new SignatureKeyPairImpl("id_" + 1, publicKey, privateKey);
doReturn(kp).when(signatureKeyDao).get(anyString());
signatureKeyManager.getOrCreateKeyPair("ws1");
verify(signatureKeyDao).get(anyString());
}
@Test
public void shouldReturnSignatureKeys() throws Exception {
String wsId = "WS_id_1";
final SignatureKeyPairImpl kp = newKeyPair(wsId);
when(signatureKeyDao.get(anyString())).thenReturn(kp);
final KeyPair cachedPair = signatureKeyManager.getOrCreateKeyPair(wsId);
assertNotNull(cachedPair);
assertKeys(cachedPair.getPublic(), kp.getPublicKey());
assertKeys(cachedPair.getPrivate(), kp.getPrivateKey());
}
private SignatureKeyPairImpl newKeyPair(String id) {
final KeyPair pair = kpg.generateKeyPair();
return new SignatureKeyPairImpl(id, pair.getPublic(), pair.getPrivate());

View File

@ -121,6 +121,15 @@ public class SignatureKeyDaoTest {
dao.create(signKeyPair);
}
@Test(
expectedExceptions = ConflictException.class,
expectedExceptionsMessageRegExp =
"Unable to create signature key pair because referenced workspace with id '.*' doesn't exist")
public void throwsConflictExceptionWhenCreatingKeyPairNotExistedWs() throws Exception {
dao.create(newKeyPair("wrong_ws"));
}
@Test(expectedExceptions = NotFoundException.class)
public void throwsNoResultExceptionWhenSearchingWrongWorkspace() throws Exception {
dao.get("unknown");