Synchronize reads and writes in Spiffe SVID Manager
Signed-off-by: Max Lambrecht <maxlambrecht@gmail.com>
This commit is contained in:
parent
0a2fc88078
commit
fdff8485cf
|
|
@ -69,7 +69,7 @@ public final class X509SVIDFetcher implements Fetcher<List<X509SVID>> {
|
||||||
StreamObserver<X509SVIDResponse> observer = new StreamObserver<X509SVIDResponse>() {
|
StreamObserver<X509SVIDResponse> observer = new StreamObserver<X509SVIDResponse>() {
|
||||||
@Override
|
@Override
|
||||||
public void onNext(X509SVIDResponse value) {
|
public void onNext(X509SVIDResponse value) {
|
||||||
LOGGER.log(Level.INFO, "New SVID received ");
|
LOGGER.log(Level.FINE, "New SVID received ");
|
||||||
listener.accept(value.getSvidsList());
|
listener.accept(value.getSvidsList());
|
||||||
retryHandler.reset();
|
retryHandler.reset();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,7 +8,6 @@ import java.security.PrivateKey;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
import static java.util.Collections.EMPTY_SET;
|
import static java.util.Collections.EMPTY_SET;
|
||||||
|
|
||||||
|
|
@ -26,8 +25,16 @@ class SpiffeIdManager {
|
||||||
return INSTANCE;
|
return INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Spiffe SVID handled by this manager
|
||||||
|
*/
|
||||||
private SpiffeSVID spiffeSVID;
|
private SpiffeSVID spiffeSVID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to synchronize spiffeSVID writes and reads
|
||||||
|
*/
|
||||||
|
private final FunctionalReadWriteLock guard;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private Constructor
|
* Private Constructor
|
||||||
*
|
*
|
||||||
|
|
@ -35,33 +42,30 @@ class SpiffeIdManager {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private SpiffeIdManager() {
|
private SpiffeIdManager() {
|
||||||
Consumer<List<X509SVID>> certificateUpdater = certs -> {
|
guard = new FunctionalReadWriteLock();
|
||||||
X509SVID svid = certs.get(0);
|
|
||||||
spiffeSVID = new SpiffeSVID(svid);
|
|
||||||
};
|
|
||||||
Fetcher<List<X509SVID>> svidFetcher = new X509SVIDFetcher();
|
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() {
|
X509Certificate getCertificate() {
|
||||||
if (spiffeSVID != null) {
|
return guard.read(() -> spiffeSVID != null ? spiffeSVID.getCertificate() : null);
|
||||||
return spiffeSVID.getCertificate();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PrivateKey getPrivateKey() {
|
PrivateKey getPrivateKey() {
|
||||||
if (spiffeSVID != null) {
|
return guard.read(() -> spiffeSVID != null ? spiffeSVID.getPrivateKey() : null);
|
||||||
return spiffeSVID.getPrivateKey();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Set<X509Certificate> getTrustedCerts() {
|
Set<X509Certificate> getTrustedCerts() {
|
||||||
if (spiffeSVID != null) {
|
return guard.read(() -> spiffeSVID != null ? spiffeSVID.getBundle() : EMPTY_SET);
|
||||||
return spiffeSVID.getBundle();
|
|
||||||
}
|
|
||||||
return EMPTY_SET;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@ import static spiffe.provider.CertificateUtils.validate;
|
||||||
*/
|
*/
|
||||||
public class SpiffeTrustManager extends X509ExtendedTrustManager {
|
public class SpiffeTrustManager extends X509ExtendedTrustManager {
|
||||||
|
|
||||||
|
|
||||||
private final SpiffeIdManager spiffeIdManager;
|
private final SpiffeIdManager spiffeIdManager;
|
||||||
|
|
||||||
SpiffeTrustManager() {
|
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
|
* @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
|
* @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 {
|
private void checkPeer(X509Certificate[] chain) throws CertificateException {
|
||||||
validate(chain, spiffeIdManager.getTrustedCerts());
|
validate(chain, spiffeIdManager.getTrustedCerts());
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue