diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/jwtproxy/JwtProxyProvisioner.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/jwtproxy/JwtProxyProvisioner.java
index d962e73f361..e2790519db9 100644
--- a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/jwtproxy/JwtProxyProvisioner.java
+++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/jwtproxy/JwtProxyProvisioner.java
@@ -43,7 +43,6 @@
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.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 @@ private void ensureJwtProxyInjected(KubernetesEnvironment k8sEnv) throws Infrast
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());
diff --git a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/jwtproxy/JwtProxyProvisionerTest.java b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/jwtproxy/JwtProxyProvisionerTest.java
index c851f95564d..5bbaf043036 100644
--- a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/jwtproxy/JwtProxyProvisionerTest.java
+++ b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/jwtproxy/JwtProxyProvisionerTest.java
@@ -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()))
diff --git a/multiuser/keycloak/che-multiuser-keycloak-server/src/test/java/org/eclipse/che/multiuser/keycloak/server/KeycloakEnvironmentInitalizationFilterTest.java b/multiuser/keycloak/che-multiuser-keycloak-server/src/test/java/org/eclipse/che/multiuser/keycloak/server/KeycloakEnvironmentInitalizationFilterTest.java
index 66a86cf0880..14f74516141 100644
--- a/multiuser/keycloak/che-multiuser-keycloak-server/src/test/java/org/eclipse/che/multiuser/keycloak/server/KeycloakEnvironmentInitalizationFilterTest.java
+++ b/multiuser/keycloak/che-multiuser-keycloak-server/src/test/java/org/eclipse/che/multiuser/keycloak/server/KeycloakEnvironmentInitalizationFilterTest.java
@@ -85,7 +85,7 @@ public void setUp() throws Exception {
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
diff --git a/multiuser/machine-auth/che-multiuser-machine-authentication/pom.xml b/multiuser/machine-auth/che-multiuser-machine-authentication/pom.xml
index 48776f1c227..3017149ebfc 100644
--- a/multiuser/machine-auth/che-multiuser-machine-authentication/pom.xml
+++ b/multiuser/machine-auth/che-multiuser-machine-authentication/pom.xml
@@ -90,10 +90,6 @@
org.eclipse.che.core
che-core-api-workspace-shared
-
- org.eclipse.che.core
- che-core-commons-annotations
-
org.eclipse.che.core
che-core-commons-auth
diff --git a/multiuser/machine-auth/che-multiuser-machine-authentication/src/main/java/org/eclipse/che/multiuser/machine/authentication/server/MachineLoginFilter.java b/multiuser/machine-auth/che-multiuser-machine-authentication/src/main/java/org/eclipse/che/multiuser/machine/authentication/server/MachineLoginFilter.java
index be7dad2fb77..1d5bbd3db4a 100644
--- a/multiuser/machine-auth/che-multiuser-machine-authentication/src/main/java/org/eclipse/che/multiuser/machine/authentication/server/MachineLoginFilter.java
+++ b/multiuser/machine-auth/che-multiuser-machine-authentication/src/main/java/org/eclipse/che/multiuser/machine/authentication/server/MachineLoginFilter.java
@@ -43,6 +43,8 @@
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 @@
@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;
diff --git a/multiuser/machine-auth/che-multiuser-machine-authentication/src/main/java/org/eclipse/che/multiuser/machine/authentication/server/MachineSigningKeyResolver.java b/multiuser/machine-auth/che-multiuser-machine-authentication/src/main/java/org/eclipse/che/multiuser/machine/authentication/server/MachineSigningKeyResolver.java
index d108bbedb17..c8abeaf7306 100644
--- a/multiuser/machine-auth/che-multiuser-machine-authentication/src/main/java/org/eclipse/che/multiuser/machine/authentication/server/MachineSigningKeyResolver.java
+++ b/multiuser/machine-auth/che-multiuser-machine-authentication/src/main/java/org/eclipse/che/multiuser/machine/authentication/server/MachineSigningKeyResolver.java
@@ -21,8 +21,8 @@
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 Key resolveSigningKey(JwsHeader header, Claims claims) {
"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);
}
}
}
diff --git a/multiuser/machine-auth/che-multiuser-machine-authentication/src/main/java/org/eclipse/che/multiuser/machine/authentication/server/MachineTokenRegistry.java b/multiuser/machine-auth/che-multiuser-machine-authentication/src/main/java/org/eclipse/che/multiuser/machine/authentication/server/MachineTokenRegistry.java
index 5deb41b95ad..41faaf151bd 100644
--- a/multiuser/machine-auth/che-multiuser-machine-authentication/src/main/java/org/eclipse/che/multiuser/machine/authentication/server/MachineTokenRegistry.java
+++ b/multiuser/machine-auth/che-multiuser-machine-authentication/src/main/java/org/eclipse/che/multiuser/machine/authentication/server/MachineTokenRegistry.java
@@ -33,7 +33,9 @@
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 MachineTokenRegistry(SignatureKeyManager signatureKeyManager, UserManager
* @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 wsRow = tokens.row(workspaceId);
@@ -77,41 +79,43 @@ public String getOrCreateToken(String userId, String workspaceId) {
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 header = new HashMap<>(2);
- header.put("kind", MACHINE_TOKEN_KIND);
- header.put("kid", workspaceId);
- final Map 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 header = new HashMap<>(2);
+ header.put("kind", MACHINE_TOKEN_KIND);
+ header.put("kid", workspaceId);
+ final Map 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);
+ }
}
/**
diff --git a/multiuser/machine-auth/che-multiuser-machine-authentication/src/main/java/org/eclipse/che/multiuser/machine/authentication/server/signature/SignatureKeyManager.java b/multiuser/machine-auth/che-multiuser-machine-authentication/src/main/java/org/eclipse/che/multiuser/machine/authentication/server/signature/SignatureKeyManager.java
index 3a8b1e937a1..dcf0f0e374e 100644
--- a/multiuser/machine-auth/che-multiuser-machine-authentication/src/main/java/org/eclipse/che/multiuser/machine/authentication/server/signature/SignatureKeyManager.java
+++ b/multiuser/machine-auth/che-multiuser-machine-authentication/src/main/java/org/eclipse/che/multiuser/machine/authentication/server/signature/SignatureKeyManager.java
@@ -15,9 +15,6 @@
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.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.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 cachedPair;
-
@Inject
public SignatureKeyManager(
@Named("che.auth.signature_key_size") int keySize,
@@ -84,19 +76,6 @@ public SignatureKeyManager(
this.algorithm = algorithm;
this.eventService = eventService;
this.signatureKeyDao = signatureKeyDao;
-
- this.cachedPair =
- CacheBuilder.newBuilder()
- .maximumSize(100)
- .expireAfterAccess(2, TimeUnit.HOURS)
- .build(
- new CacheLoader() {
- @Override
- public KeyPair load(String key) throws Exception {
- return loadKeyPair(key);
- }
- });
-
this.workspaceEventsSubscriber =
new EventSubscriber() {
@Override
@@ -108,21 +87,34 @@ public void onEvent(WorkspaceStatusEvent event) {
};
}
- /** 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,48 +123,43 @@ public void removeKeyPair(String workspaceId) {
}
}
- /** 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);
+ /** Returns key spec by key format and encoded data. */
+ private EncodedKeySpec getKeySpec(SignatureKey key) {
+ switch (key.getFormat()) {
+ case PKCS_8:
+ return new PKCS8EncodedKeySpec(key.getEncoded());
+ case X_509:
+ return new X509EncodedKeySpec(key.getEncoded());
+ default:
+ throw new IllegalArgumentException(
+ String.format("Unsupported key spec '%s' for signature keys", key.getFormat()));
}
- 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 {
+ private KeyPair toJavaKeyPair(SignatureKeyPair keyPair) throws SignatureKeyManagerException {
try {
final PrivateKey privateKey =
KeyFactory.getInstance(keyPair.getPrivateKey().getAlgorithm())
@@ -183,20 +170,7 @@ public static KeyPair toJavaKeyPair(SignatureKeyPair keyPair) throws ServerExcep
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) {
- switch (key.getFormat()) {
- case PKCS_8:
- return new PKCS8EncodedKeySpec(key.getEncoded());
- case X_509:
- return new X509EncodedKeySpec(key.getEncoded());
- default:
- throw new IllegalArgumentException(
- String.format("Unsupported key spec '%s' for signature keys", key.getFormat()));
+ throw new SignatureKeyManagerException("Failed to convert signature key pair to Java keys.");
}
}
diff --git a/multiuser/machine-auth/che-multiuser-machine-authentication/src/main/java/org/eclipse/che/multiuser/machine/authentication/server/signature/SignatureKeyManagerException.java b/multiuser/machine-auth/che-multiuser-machine-authentication/src/main/java/org/eclipse/che/multiuser/machine/authentication/server/signature/SignatureKeyManagerException.java
new file mode 100644
index 00000000000..a4d7c972f39
--- /dev/null
+++ b/multiuser/machine-auth/che-multiuser-machine-authentication/src/main/java/org/eclipse/che/multiuser/machine/authentication/server/signature/SignatureKeyManagerException.java
@@ -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);
+ }
+}
diff --git a/multiuser/machine-auth/che-multiuser-machine-authentication/src/main/java/org/eclipse/che/multiuser/machine/authentication/server/signature/SignaturePublicKeyEnvProvider.java b/multiuser/machine-auth/che-multiuser-machine-authentication/src/main/java/org/eclipse/che/multiuser/machine/authentication/server/signature/SignaturePublicKeyEnvProvider.java
index 54874aa99e3..c4944a72a72 100644
--- a/multiuser/machine-auth/che-multiuser-machine-authentication/src/main/java/org/eclipse/che/multiuser/machine/authentication/server/signature/SignaturePublicKeyEnvProvider.java
+++ b/multiuser/machine-auth/che-multiuser-machine-authentication/src/main/java/org/eclipse/che/multiuser/machine/authentication/server/signature/SignaturePublicKeyEnvProvider.java
@@ -15,7 +15,6 @@
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 Pair get(RuntimeIdentity runtimeIdentity) throws Infrastr
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());
diff --git a/multiuser/machine-auth/che-multiuser-machine-authentication/src/main/java/org/eclipse/che/multiuser/machine/authentication/server/signature/jpa/JpaSignatureKeyDao.java b/multiuser/machine-auth/che-multiuser-machine-authentication/src/main/java/org/eclipse/che/multiuser/machine/authentication/server/signature/jpa/JpaSignatureKeyDao.java
index b3d60106282..fdf20a8483d 100644
--- a/multiuser/machine-auth/che-multiuser-machine-authentication/src/main/java/org/eclipse/che/multiuser/machine/authentication/server/signature/jpa/JpaSignatureKeyDao.java
+++ b/multiuser/machine-auth/che-multiuser-machine-authentication/src/main/java/org/eclipse/che/multiuser/machine/authentication/server/signature/jpa/JpaSignatureKeyDao.java
@@ -29,6 +29,7 @@
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 SignatureKeyPairImpl create(SignatureKeyPairImpl keyPair)
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()));
diff --git a/multiuser/machine-auth/che-multiuser-machine-authentication/src/test/java/org/eclipse/che/multiuser/machine/authentication/server/MachineLoginFilterTest.java b/multiuser/machine-auth/che-multiuser-machine-authentication/src/test/java/org/eclipse/che/multiuser/machine/authentication/server/MachineLoginFilterTest.java
index a894a0d0039..136b024c94d 100644
--- a/multiuser/machine-auth/che-multiuser-machine-authentication/src/test/java/org/eclipse/che/multiuser/machine/authentication/server/MachineLoginFilterTest.java
+++ b/multiuser/machine-auth/che-multiuser-machine-authentication/src/test/java/org/eclipse/che/multiuser/machine/authentication/server/MachineLoginFilterTest.java
@@ -107,7 +107,7 @@ private void setUp() throws Exception {
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 @@ private void setUp() throws Exception {
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 void testNotProceedRequestWhenSignatureCheckIsFailed() throws Exception {
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 void testSetErrorInResponseWhenNoUserFoundForProvidedToken() throws Excep
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 void testSetErrorInResponseWhenUnableToGetUserForProvidedToken() throws E
machineLoginFilter.doFilter(getRequestMock(), responseMock, chainMock);
- verify(keyManagerMock).getKeyPair(eq(WORKSPACE_ID));
+ verify(keyManagerMock).getOrCreateKeyPair(eq(WORKSPACE_ID));
verify(userManagerMock).getById(anyString());
verify(responseMock)
.sendError(
diff --git a/multiuser/machine-auth/che-multiuser-machine-authentication/src/test/java/org/eclipse/che/multiuser/machine/authentication/server/MachineTokenRegistryTest.java b/multiuser/machine-auth/che-multiuser-machine-authentication/src/test/java/org/eclipse/che/multiuser/machine/authentication/server/MachineTokenRegistryTest.java
index 98ecd5fe80a..e56152c9a15 100644
--- a/multiuser/machine-auth/che-multiuser-machine-authentication/src/test/java/org/eclipse/che/multiuser/machine/authentication/server/MachineTokenRegistryTest.java
+++ b/multiuser/machine-auth/che-multiuser-machine-authentication/src/test/java/org/eclipse/che/multiuser/machine/authentication/server/MachineTokenRegistryTest.java
@@ -31,6 +31,8 @@
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 @@ private void setUp() throws Exception {
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 void testCreatesNewTokenWhenNoPreviouslyCreatedFound() throws Exception {
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"));
diff --git a/multiuser/machine-auth/che-multiuser-machine-authentication/src/test/java/org/eclipse/che/multiuser/machine/authentication/server/signature/SignatureKeyManagerTest.java b/multiuser/machine-auth/che-multiuser-machine-authentication/src/test/java/org/eclipse/che/multiuser/machine/authentication/server/signature/SignatureKeyManagerTest.java
index 6c58d9c0bc5..2f968ebc5b8 100644
--- a/multiuser/machine-auth/che-multiuser-machine-authentication/src/test/java/org/eclipse/che/multiuser/machine/authentication/server/signature/SignatureKeyManagerTest.java
+++ b/multiuser/machine-auth/che-multiuser-machine-authentication/src/test/java/org/eclipse/che/multiuser/machine/authentication/server/signature/SignatureKeyManagerTest.java
@@ -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 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.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;
@@ -72,82 +67,43 @@ public void createEntities() throws Exception {
}
@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) 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"));
+ public void shouldRemoveKeyPairOnWorkspaceStop() throws Exception {
+ final String wsId = "ws123";
+ signatureKeyManager.subscribe();
+ verify(eventService).subscribe(captor.capture());
+ final EventSubscriber subscriber = captor.getValue();
- signatureKeyManager.getKeyPair("ws1");
+ subscriber.onEvent(
+ DtoFactory.newDto(WorkspaceStatusEvent.class)
+ .withStatus(WorkspaceStatus.STOPPED)
+ .withWorkspaceId(wsId));
- verify(signatureKeyDao).get(anyString());
- verify(signatureKeyDao).create(any(SignatureKeyPairImpl.class));
+ verify(signatureKeyDao, times(1)).remove(eq(wsId));
}
- @Test(expectedExceptions = ServerException.class)
- public void testThrowsExceptionWhenAlgorithmIsNotSupported() throws Exception {
+ @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.getKeyPair("ws1");
+ signatureKeyManager.getOrCreateKeyPair("ws1");
verify(signatureKeyDao).get(anyString());
}
@Test
- public void shouldRemoveKeyPairOnWorkspaceStop() throws Exception {
- final String wsId = "ws123";
- signatureKeyManager.subscribe();
- verify(eventService).subscribe(captor.capture());
- final EventSubscriber subscriber = captor.getValue();
+ public void shouldReturnSignatureKeys() throws Exception {
+ String wsId = "WS_id_1";
+ final SignatureKeyPairImpl kp = newKeyPair(wsId);
+ when(signatureKeyDao.get(anyString())).thenReturn(kp);
- subscriber.onEvent(
- DtoFactory.newDto(WorkspaceStatusEvent.class)
- .withStatus(WorkspaceStatus.STOPPED)
- .withWorkspaceId(wsId));
+ final KeyPair cachedPair = signatureKeyManager.getOrCreateKeyPair(wsId);
- verify(signatureKeyDao, times(1)).remove(eq(wsId));
+ assertNotNull(cachedPair);
+ assertKeys(cachedPair.getPublic(), kp.getPublicKey());
+ assertKeys(cachedPair.getPrivate(), kp.getPrivateKey());
}
private SignatureKeyPairImpl newKeyPair(String id) {
diff --git a/multiuser/machine-auth/che-multiuser-machine-authentication/src/test/java/org/eclipse/che/multiuser/machine/authentication/server/signature/spi/tck/SignatureKeyDaoTest.java b/multiuser/machine-auth/che-multiuser-machine-authentication/src/test/java/org/eclipse/che/multiuser/machine/authentication/server/signature/spi/tck/SignatureKeyDaoTest.java
index 18f1774ff6b..516635ef114 100644
--- a/multiuser/machine-auth/che-multiuser-machine-authentication/src/test/java/org/eclipse/che/multiuser/machine/authentication/server/signature/spi/tck/SignatureKeyDaoTest.java
+++ b/multiuser/machine-auth/che-multiuser-machine-authentication/src/test/java/org/eclipse/che/multiuser/machine/authentication/server/signature/spi/tck/SignatureKeyDaoTest.java
@@ -121,6 +121,15 @@ public void throwsConflictExceptionWhenCreatingSignatureKeyPair() throws Excepti
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");