Synchronize reads and writes in Spiffe SVID Manager

Signed-off-by: Max Lambrecht <maxlambrecht@gmail.com>
This commit is contained in:
Max Lambrecht 2018-08-17 10:11:07 -03:00
parent 0a2fc88078
commit fdff8485cf
4 changed files with 55 additions and 21 deletions

View File

@ -69,7 +69,7 @@ public final class X509SVIDFetcher implements Fetcher<List<X509SVID>> {
StreamObserver<X509SVIDResponse> observer = new StreamObserver<X509SVIDResponse>() {
@Override
public void onNext(X509SVIDResponse value) {
LOGGER.log(Level.INFO, "New SVID received ");
LOGGER.log(Level.FINE, "New SVID received ");
listener.accept(value.getSvidsList());
retryHandler.reset();
}

View File

@ -0,0 +1,31 @@
package spiffe.provider;
import java.util.concurrent.locks.StampedLock;
import java.util.function.Supplier;
public class FunctionalReadWriteLock {
private final StampedLock lock;
public FunctionalReadWriteLock() {
this.lock = new StampedLock();
}
public <T> T read(Supplier<T> supplier) {
long stamp = lock.readLock();
try {
return supplier.get();
} finally {
lock.unlockRead(stamp);
}
}
public void write(Runnable runnable) {
long stamp = lock.writeLock();
try {
runnable.run();
} finally {
lock.unlockWrite(stamp);
}
}
}

View File

@ -8,7 +8,6 @@ import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import static java.util.Collections.EMPTY_SET;
@ -26,8 +25,16 @@ class SpiffeIdManager {
return INSTANCE;
}
/**
* The Spiffe SVID handled by this manager
*/
private SpiffeSVID spiffeSVID;
/**
* Used to synchronize spiffeSVID writes and reads
*/
private final FunctionalReadWriteLock guard;
/**
* Private Constructor
*
@ -35,33 +42,30 @@ class SpiffeIdManager {
*
*/
private SpiffeIdManager() {
Consumer<List<X509SVID>> certificateUpdater = certs -> {
X509SVID svid = certs.get(0);
spiffeSVID = new SpiffeSVID(svid);
};
guard = new FunctionalReadWriteLock();
Fetcher<List<X509SVID>> svidFetcher = new X509SVIDFetcher();
svidFetcher.registerListener(certificateUpdater);
svidFetcher.registerListener(this::updateSVID);
}
/**
* Method used as callback that gets executed whenever an SVID update is pushed by the Workload API
* Uses a write lock to synchronize access to spiffeSVID
*/
private void updateSVID(List<X509SVID> certs) {
X509SVID svid = certs.get(0);
guard.write(() -> spiffeSVID = new SpiffeSVID(svid));
}
X509Certificate getCertificate() {
if (spiffeSVID != null) {
return spiffeSVID.getCertificate();
}
return null;
return guard.read(() -> spiffeSVID != null ? spiffeSVID.getCertificate() : null);
}
PrivateKey getPrivateKey() {
if (spiffeSVID != null) {
return spiffeSVID.getPrivateKey();
}
return null;
return guard.read(() -> spiffeSVID != null ? spiffeSVID.getPrivateKey() : null);
}
@SuppressWarnings("unchecked")
Set<X509Certificate> getTrustedCerts() {
if (spiffeSVID != null) {
return spiffeSVID.getBundle();
}
return EMPTY_SET;
return guard.read(() -> spiffeSVID != null ? spiffeSVID.getBundle() : EMPTY_SET);
}
}

View File

@ -15,7 +15,6 @@ import static spiffe.provider.CertificateUtils.validate;
*/
public class SpiffeTrustManager extends X509ExtendedTrustManager {
private final SpiffeIdManager spiffeIdManager;
SpiffeTrustManager() {
@ -85,7 +84,7 @@ public class SpiffeTrustManager extends X509ExtendedTrustManager {
*
* @param chain an array of X509Certificate that contains the Peer's SVID to be validated
* @throws CertificateException when either the Peer's certificate doesn't chain to any Trusted CA
* or the SPIFFE ID is not authorized.
*
*/
private void checkPeer(X509Certificate[] chain) throws CertificateException {
validate(chain, spiffeIdManager.getTrustedCerts());