Minor fixes

Signed-off-by: Max Lambrecht <maxlambrecht@gmail.com>
This commit is contained in:
Max Lambrecht 2020-04-26 15:16:11 -03:00
parent 44cda6e809
commit ecabc0f288
23 changed files with 139 additions and 122 deletions

View File

@ -137,7 +137,7 @@ public class CertificateUtils {
// Create an instance of PKIXParameters used as input for the PKIX CertPathValidator
private static PKIXParameters toPkixParameters(List<X509Certificate> trustedCerts) throws CertificateException, InvalidAlgorithmParameterException {
if (trustedCerts == null || trustedCerts.size() == 0) {
if (trustedCerts == null || trustedCerts.isEmpty()) {
throw new CertificateException("No trusted Certs");
}
@ -166,4 +166,6 @@ public class CertificateUtils {
val decoder = Base64.getDecoder();
return decoder.decode(privateKey);
}
private CertificateUtils() {}
}

View File

@ -41,7 +41,7 @@ public class SpiffeId {
val path = Arrays.stream(segments)
.filter(StringUtils::isNotBlank)
.map(SpiffeId::normalize)
.map(s -> "/" + s)
.map(s -> '/' + s)
.collect(Collectors.joining());
return new SpiffeId(trustDomain, path);
}

View File

@ -68,10 +68,11 @@ public class SpiffeIdUtils {
* @throws IllegalArgumentException if any of the SPIFFE IDs in the file cannot be parsed
*/
public static List<SpiffeId> getSpiffeIdListFromFile(final Path spiffeIdsFile) throws IOException {
Stream<String> lines = Files.lines(spiffeIdsFile);
return lines
.map(SpiffeId::parse)
.collect(Collectors.toList());
try (Stream<String> lines = Files.lines(spiffeIdsFile)) {
return lines
.map(SpiffeId::parse)
.collect(Collectors.toList());
}
}
/**
@ -95,4 +96,6 @@ public class SpiffeIdUtils {
.map(SpiffeId::parse)
.collect(Collectors.toList());
}
private SpiffeIdUtils() {}
}

View File

@ -17,10 +17,10 @@ import static java.lang.String.format;
@Value
public class TrustDomain {
String trustDomain;
String name;
private TrustDomain(String trustDomain) {
this.trustDomain = trustDomain;
this.name = trustDomain;
}
/**
@ -51,7 +51,7 @@ public class TrustDomain {
*/
@Override
public String toString() {
return trustDomain;
return name;
}
private static String normalize(String s) {

View File

@ -17,5 +17,5 @@ public interface JwtSvidSource {
*
* @throws //TODO: declare thrown exceptions
*/
JwtSvid FetchJwtSvid(SpiffeId subject, String audience, String... extraAudiences);
JwtSvid fetchJwtSvid(SpiffeId subject, String audience, String... extraAudiences);
}

View File

@ -62,4 +62,6 @@ public class X509SvidValidator {
throw new CertificateException(String.format("SPIFFE ID %s in x509Certificate is not accepted", spiffeId));
}
}
private X509SvidValidator() {}
}

View File

@ -62,76 +62,14 @@ public class Address {
String error = null;
switch (scheme) {
case "unix": {
if (parsedAddress.isOpaque() && parsedAddress.isAbsolute()) {
error = "Workload endpoint unix socket URI must not be opaque: %s";
break;
}
if (StringUtils.isNotBlank(parsedAddress.getUserInfo())) {
error = "Workload endpoint unix socket URI must not include user info: %s";
break;
}
if (StringUtils.isBlank(parsedAddress.getHost()) && StringUtils.isBlank(parsedAddress.getPath())) {
error = "Workload endpoint unix socket URI must include a path: %s";
break;
}
if (StringUtils.isNotBlank(parsedAddress.getRawQuery())) {
error = "Workload endpoint unix socket URI must not include query values: %s";
break;
}
if (StringUtils.isNotBlank(parsedAddress.getFragment())) {
error = "Workload endpoint unix socket URI must not include a fragment: %s";
}
case "unix":
error = validateUnixAddress(parsedAddress);
break;
}
case "tcp": {
if (parsedAddress.isOpaque() && parsedAddress.isAbsolute()) {
error = "Workload endpoint tcp socket URI must not be opaque: %s";
break;
}
if (StringUtils.isNotBlank(parsedAddress.getUserInfo())) {
error = "Workload endpoint tcp socket URI must not include user info: %s";
break;
}
if (StringUtils.isBlank(parsedAddress.getHost())) {
error = "Workload endpoint tcp socket URI must include a host: %s";
break;
}
if (StringUtils.isNotBlank(parsedAddress.getPath())) {
error = "Workload endpoint tcp socket URI must not include a path: %s";
break;
}
if (StringUtils.isNotBlank(parsedAddress.getRawQuery())) {
error = "Workload endpoint tcp socket URI must not include query values: %s";
break;
}
if (StringUtils.isNotBlank(parsedAddress.getFragment())) {
error = "Workload endpoint tcp socket URI must not include a fragment: %s";
break;
}
String ip = parseIp(parsedAddress.getHost());
if (StringUtils.isBlank(ip)) {
error = "Workload endpoint tcp socket URI host component must be an IP:port: %s";
break;
}
int port = parsedAddress.getPort();
if (port == -1) {
error = "Workload endpoint tcp socket URI host component must include a port: %s";
}
case "tcp":
error = validateTcpAddress(parsedAddress);
break;
}
default:
error = "Workload endpoint socket URI must have a tcp:// or unix:// scheme: %s";
}
if (StringUtils.isNotBlank(error)) {
@ -141,6 +79,66 @@ public class Address {
return parsedAddress;
}
private static String validateUnixAddress(URI parsedAddress) {
if (parsedAddress.isOpaque() && parsedAddress.isAbsolute()) {
return "Workload endpoint unix socket URI must not be opaque: %s";
}
if (StringUtils.isNotBlank(parsedAddress.getUserInfo())) {
return "Workload endpoint unix socket URI must not include user info: %s";
}
if (StringUtils.isBlank(parsedAddress.getHost()) && StringUtils.isBlank(parsedAddress.getPath())) {
return "Workload endpoint unix socket URI must include a path: %s";
}
if (StringUtils.isNotBlank(parsedAddress.getRawQuery())) {
return "Workload endpoint unix socket URI must not include query values: %s";
}
if (StringUtils.isNotBlank(parsedAddress.getFragment())) {
return "Workload endpoint unix socket URI must not include a fragment: %s";
}
return "";
}
private static String validateTcpAddress(URI parsedAddress) {
if (parsedAddress.isOpaque() && parsedAddress.isAbsolute()) {
return "Workload endpoint tcp socket URI must not be opaque: %s";
}
if (StringUtils.isNotBlank(parsedAddress.getUserInfo())) {
return "Workload endpoint tcp socket URI must not include user info: %s";
}
if (StringUtils.isBlank(parsedAddress.getHost())) {
return "Workload endpoint tcp socket URI must include a host: %s";
}
if (StringUtils.isNotBlank(parsedAddress.getPath())) {
return "Workload endpoint tcp socket URI must not include a path: %s";
}
if (StringUtils.isNotBlank(parsedAddress.getRawQuery())) {
return "Workload endpoint tcp socket URI must not include query values: %s";
}
if (StringUtils.isNotBlank(parsedAddress.getFragment())) {
return "Workload endpoint tcp socket URI must not include a fragment: %s";
}
String ip = parseIp(parsedAddress.getHost());
if (StringUtils.isBlank(ip)) {
return "Workload endpoint tcp socket URI host component must be an IP:port: %s";
}
int port = parsedAddress.getPort();
if (port == -1) {
return "Workload endpoint tcp socket URI host component must include a port: %s";
}
return "";
}
private static boolean isValid(String scheme) {
return (StringUtils.isNotBlank(scheme) && VALID_SCHEMES.contains(scheme));
}
@ -153,4 +151,6 @@ public class Address {
return null;
}
}
private Address() {}
}

View File

@ -31,7 +31,7 @@ public class JwtSource implements JwtSvidSource, JwtBundleSource {
}
@Override
public JwtSvid FetchJwtSvid(SpiffeId subject, String audience, String... extraAudiences) {
public JwtSvid fetchJwtSvid(SpiffeId subject, String audience, String... extraAudiences) {
throw new NotImplementedException("Not implemented");
}
}

View File

@ -6,8 +6,6 @@ package spiffe.workloadapi;
* @param <T> is the type of the updates.
*/
public interface Watcher<T> {
void OnUpdate(final T update);
void OnError(final Throwable e);
void onUpdate(final T update);
void onError(final Throwable e);
}

View File

@ -125,19 +125,19 @@ public class WorkloadApiClient implements Closeable {
try {
x509Context = GrpcConversionUtils.toX509Context(value);
} catch (CertificateException | X509SvidException e) {
watcher.OnError(new X509ContextException("Error processing X509 Context update", e));
watcher.onError(new X509ContextException("Error processing X509 Context update", e));
}
watcher.OnUpdate(x509Context);
watcher.onUpdate(x509Context);
}
@Override
public void onError(Throwable t) {
watcher.OnError(new X509ContextException("Error getting X509Context", t));
watcher.onError(new X509ContextException("Error getting X509Context", t));
}
@Override
public void onCompleted() {
watcher.OnError(new X509ContextException("Unexpected completed stream"));
watcher.onError(new X509ContextException("Unexpected completed stream"));
}
};
Context.CancellableContext cancellableContext;

View File

@ -158,27 +158,27 @@ public class X509Source implements X509SvidSource, X509BundleSource, Closeable {
private void setX509ContextWatcher() {
workloadApiClient.watchX509Context(new Watcher<X509Context>() {
@Override
public void OnUpdate(X509Context update) {
public void onUpdate(X509Context update) {
log.log(Level.INFO, "Received X509Context update");
setX509Context(update);
}
@Override
public void OnError(Throwable error) {
public void onError(Throwable error) {
log.log(Level.SEVERE, String.format("Error in X509Context watcher: %s %n %s", error.getMessage(), ExceptionUtils.getStackTrace(error)));
}
});
}
private void setX509Context(@NonNull final X509Context update) {
X509Svid svid;
X509Svid svidUpdate;
if (picker == null) {
svid = update.getDefaultSvid();
svidUpdate = update.getDefaultSvid();
} else {
svid = picker.apply(update.getX509Svid());
svidUpdate = picker.apply(update.getX509Svid());
}
synchronized (this) {
this.svid = svid;
this.svid = svidUpdate;
this.bundles = update.getX509BundleSet();
}
}

View File

@ -47,4 +47,6 @@ public class GrpcConversionUtils {
}
return x509SvidList;
}
private GrpcConversionUtils() {}
}

View File

@ -65,4 +65,6 @@ public class GrpcManagedChannelFactory {
channelBuilder.eventLoopGroup(new NioEventLoopGroup());
}
private GrpcManagedChannelFactory() {}
}

View File

@ -25,7 +25,7 @@ class KeyStore {
private final KeyStoreType keyStoreType;
private final char[] keyStorePassword;
private java.security.KeyStore keyStore;
private java.security.KeyStore javaKeyStore;
private File keyStoreFile;
@Builder
@ -41,7 +41,7 @@ class KeyStore {
private void setupKeyStore() throws KeyStoreException {
this.keyStoreFile = new File(keyStoreFilePath.toUri());
this.keyStore = loadKeyStore(keyStoreFile);
this.javaKeyStore = loadKeyStore(keyStoreFile);
}
@ -70,7 +70,7 @@ class KeyStore {
*/
void storePrivateKey(final PrivateKeyEntry privateKeyEntry) throws KeyStoreException {
// Store PrivateKey Entry in KeyStore
keyStore.setKeyEntry(
javaKeyStore.setKeyEntry(
privateKeyEntry.getAlias(),
privateKeyEntry.getPrivateKey(),
privateKeyEntry.getPassword(),
@ -85,7 +85,7 @@ class KeyStore {
*/
void storeBundleEntry(BundleEntry bundleEntry) throws KeyStoreException {
// Store Bundle Entry in KeyStore
this.keyStore.setCertificateEntry(
this.javaKeyStore.setCertificateEntry(
bundleEntry.getAlias(),
bundleEntry.getCertificate()
);
@ -95,7 +95,7 @@ class KeyStore {
// Flush KeyStore to disk, to the configured (@see keyStoreFilePath)
private void flush() throws KeyStoreException {
try {
keyStore.store(new FileOutputStream(keyStoreFile), keyStorePassword);
javaKeyStore.store(new FileOutputStream(keyStoreFile), keyStorePassword);
} catch (IOException | NoSuchAlgorithmException | CertificateException e) {
throw new KeyStoreException(e);
}

View File

@ -96,18 +96,18 @@ public class KeyStoreHelper {
private void setX509ContextWatcher(WorkloadApiClient workloadApiClient, CountDownLatch countDownLatch) {
workloadApiClient.watchX509Context(new Watcher<X509Context>() {
@Override
public void OnUpdate(X509Context update) {
public void onUpdate(X509Context update) {
log.log(Level.INFO, "Received X509Context update");
try {
storeX509ContextUpdate(update);
} catch (KeyStoreException e) {
this.OnError(e);
this.onError(e);
}
countDownLatch.countDown();
}
@Override
public void OnError(Throwable t) {
public void onError(Throwable t) {
throw new RuntimeException(t);
}
});

View File

@ -36,7 +36,7 @@ public final class SpiffeKeyManager extends X509ExtendedKeyManager {
@Override
public X509Certificate[] getCertificateChain(String alias) {
if (!Objects.equals(alias, DEFAULT_ALIAS)) {
return null;
return new X509Certificate[0];
}
X509Svid x509Svid = x509SvidSource.getX509Svid();
return x509Svid.getChainArray();

View File

@ -30,7 +30,7 @@ public final class SpiffeKeyStore extends KeyStoreSpi {
@Override
public Certificate[] engineGetCertificateChain(String alias) {
return null;
return new Certificate[0];
}
@Override

View File

@ -13,4 +13,6 @@ class SpiffeProviderConstants {
// alias used by the SpiffeKeyStore
static final String DEFAULT_ALIAS = "Spiffe";
private SpiffeProviderConstants() {}
}

View File

@ -74,4 +74,6 @@ public final class SpiffeSslContextFactory {
this.sslProtocol = sslProtocol;
}
}
private SpiffeSslContextFactory() {}
}

View File

@ -25,15 +25,15 @@ public final class SpiffeTrustManager extends X509ExtendedTrustManager {
private final Supplier<List<SpiffeId>> acceptedSpiffeIdsSupplier;
/**
* Creates a SpiffeTrustManager with a X509BundleSource used to provide the trusted
* Creates a SpiffeTrustManager with a X509 bundle source used to provide the trusted
* bundles, and a Supplier of a List of accepted SpiffeIds to be used during peer SVID validation.
*
* @param X509BundleSource an implementation of a {@link X509BundleSource}
* @param x509BundleSource an implementation of a {@link X509BundleSource}
* @param acceptedSpiffeIdsSupplier a Supplier of a list of accepted SPIFFE IDs.
*/
public SpiffeTrustManager(X509BundleSource X509BundleSource,
public SpiffeTrustManager(X509BundleSource x509BundleSource,
Supplier<List<SpiffeId>> acceptedSpiffeIdsSupplier) {
this.x509BundleSource = X509BundleSource;
this.x509BundleSource = x509BundleSource;
this.acceptedSpiffeIdsSupplier = acceptedSpiffeIdsSupplier;
}

View File

@ -75,9 +75,8 @@ public class HttpsClient {
}
static List<SpiffeId> listOfSpiffeIds() {
try {
Path path = Paths.get("java-spiffe-provider/src/main/java/spiffe/provider/examples/spiffeIds.txt");
Stream<String> lines = Files.lines(path);
Path path = Paths.get("java-spiffe-provider/src/main/java/spiffe/provider/examples/spiffeIds.txt");
try (Stream<String> lines = Files.lines(path)) {
return lines
.map(SpiffeId::parse)
.collect(Collectors.toList());

View File

@ -58,13 +58,14 @@ public class HttpsServer {
SSLContext sslContext = SpiffeSslContextFactory.getSslContext(sslContextOptions);
SSLServerSocketFactory sslServerSocketFactory = sslContext.getServerSocketFactory();
SSLServerSocket sslServerSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket(port);
// Server will validate Client chain and SPIFFE ID
sslServerSocket.setNeedClientAuth(true);
try (SSLServerSocket sslServerSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket(port)) {
// Server will validate Client chain and SPIFFE ID
sslServerSocket.setNeedClientAuth(true);
SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
new WorkloadThread(sslSocket, x509Source).start();
SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
new WorkloadThread(sslSocket, x509Source).start();
}
}
}

View File

@ -1,5 +1,6 @@
package spiffe.provider.examples;
import lombok.extern.java.Log;
import spiffe.internal.CertificateUtils;
import spiffe.spiffeid.SpiffeId;
import spiffe.workloadapi.X509Source;
@ -8,7 +9,9 @@ import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import java.io.*;
import java.security.cert.X509Certificate;
import java.util.logging.Level;
@Log
class WorkloadThread extends Thread {
private final X509Source x509Source;
@ -19,15 +22,16 @@ class WorkloadThread extends Thread {
this.x509Source = x509Source;
}
@Override
public void run() {
try {
sslSocket.startHandshake();
SSLSession sslSession = sslSocket.getSession();
System.out.println("SSLSession :");
System.out.println("\tProtocol : " + sslSession.getProtocol());
System.out.println("\tCipher suite : " + sslSession.getCipherSuite());
System.out.println();
log.info("SSLSession :\n");
log.info("\tProtocol : \n" + sslSession.getProtocol());
log.info("\tCipher suite \n: " + sslSession.getCipherSuite());
// Start handling application content
InputStream inputStream = sslSocket.getInputStream();
@ -50,14 +54,14 @@ class WorkloadThread extends Thread {
// Read message from peer
String line;
while ((line = bufferedReader.readLine()) != null) {
System.out.println("Message received: " + line);
log.info("Message received: " + line);
break;
}
x509Source.close();
sslSocket.close();
} catch (Exception ex) {
ex.printStackTrace();
} catch (Exception e) {
log.log(Level.SEVERE, e.getMessage());
}
}
}