All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.uid2.shared.secure.azurecc.AzurePublicKeyProvider Maven / Gradle / Ivy

package com.uid2.shared.secure.azurecc;

import com.azure.security.attestation.AttestationClientBuilder;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap;
import com.uid2.shared.secure.AttestationException;

import java.security.PublicKey;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

// MAA certs are stored as x5c(X.509 certificate chain), not supported by Google auth lib.
// So we have to build a thin layer to fetch Azure public key.
public class AzurePublicKeyProvider implements IPublicKeyProvider {

    private final LoadingCache> publicKeyCache;

    public AzurePublicKeyProvider() {
        this.publicKeyCache = CacheBuilder.newBuilder()
                .expireAfterWrite(1L, TimeUnit.HOURS)
                .build(new CacheLoader<>() {
                    @Override
                    public Map load(String maaServerBaseUrl) throws AttestationException {
                        return loadPublicKeys(maaServerBaseUrl);
                    }
                });
    }

    @Override
    public PublicKey GetPublicKey(String maaServerBaseUrl, String kid) throws AttestationException {
        PublicKey key;
        try {
            key = publicKeyCache.get(maaServerBaseUrl).get(kid);
        }
        catch (ExecutionException e){
            throw new AttestationException(
                    String.format("Error fetching PublicKey from certificate location: %s, error: %s.", maaServerBaseUrl, e.getMessage())
            );
        }

        if(key == null){
            throw new AttestationException("Could not find PublicKey for provided keyId: " + kid);
        }
        return key;
    }

    // We don't want to reinvent the wheel. Leverage Azure Attestation client library to fetch certs.
    private static Map loadPublicKeys(String maaServerBaseUrl) throws AttestationException {
        var attestationBuilder = new AttestationClientBuilder();
        var client = attestationBuilder
                .endpoint(maaServerBaseUrl)
                .buildClient();

        var signers = client.listAttestationSigners().getAttestationSigners();

        ImmutableMap.Builder keyCacheBuilder = new ImmutableMap.Builder();

        for (var signer : signers){
            var keyId = signer.getKeyId();
            var certs = signer.getCertificates();

            // It's possible that there's a certificate chain. We will use the public key of Leaf Certificate here.
            if(!certs.isEmpty()){
                var publicKey = certs.get(0).getPublicKey();
                keyCacheBuilder.put(keyId, publicKey);
            }
        }

        var map = keyCacheBuilder.build();
        if(map.isEmpty()){
            throw new AttestationException("Fail to load certs from: " + maaServerBaseUrl);
        }

        return map;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy