package org.activityinfo.server.util.blob; import com.google.appengine.api.appidentity.AppIdentityService; import com.google.appengine.api.appidentity.PublicCertificate; import com.google.common.base.Strings; import org.activityinfo.service.DeploymentConfiguration; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.security.KeyStore; import java.security.PrivateKey; import java.security.Signature; import java.util.Collection; import java.util.logging.Level; import java.util.logging.Logger; public class DevAppIdentityService implements AppIdentityService { private static final Logger LOGGER = Logger.getLogger(DevAppIdentityService.class.getName()); private final DeploymentConfiguration config; private String serviceAccountName; private PrivateKey privateKey = null; public DevAppIdentityService(DeploymentConfiguration config) { this.config = config; try { loadPrivateKey(config); } catch(Exception e) { LOGGER.log(Level.WARNING, "Could not load primary key", e); } } private void loadPrivateKey(DeploymentConfiguration config) throws Exception { serviceAccountName = config.getProperty("service.account.name"); String keyPath = config.getProperty("service.account.p12.key.path"); String password = config.getProperty("service.account.p12.key.password"); if(Strings.isNullOrEmpty(serviceAccountName) || Strings.isNullOrEmpty(keyPath) || Strings.isNullOrEmpty(password)) { LOGGER.warning("Service account is not configured for blob store testing, add the following to your " + "~/activityinfo.properties file:\n" + "service.account.name=135288259907-k64g5vuv9en1o89on1ru16hrusvimn9t@developer" + ".gserviceaccount.com\n" + "service.account.p12.key.path=/home/alex/.ssh/bdd-dev-0bcc29c72426.p12\n" + "service.account.p12.key.password=notasecret"); } else { File keyFile = new File(keyPath); if(!keyFile.exists()) { throw new IOException("Keystore not found at " + keyFile.getAbsolutePath()); } KeyStore keystore = KeyStore.getInstance("PKCS12"); try(FileInputStream in = new FileInputStream(keyFile)) { keystore.load(in, password.toCharArray()); } privateKey = (PrivateKey)keystore.getKey("privatekey", password.toCharArray()); } } @Override public SigningResult signForApp(byte[] bytes) { if(privateKey == null) { throw new UnsupportedOperationException("Service account not configured for local development."); } try { Signature dsa = Signature.getInstance("SHA1withRSA"); dsa.initSign(privateKey); dsa.update(bytes); return new SigningResult(serviceAccountName, dsa.sign()); } catch(Exception e) { throw new RuntimeException(e); } } @Override public Collection<PublicCertificate> getPublicCertificatesForApp() { throw new UnsupportedOperationException(); } @Override public String getServiceAccountName() { return serviceAccountName; } @Override public String getDefaultGcsBucketName() { throw new UnsupportedOperationException(); } @Override public GetAccessTokenResult getAccessTokenUncached(Iterable<String> strings) { throw new UnsupportedOperationException(); } @Override public GetAccessTokenResult getAccessToken(Iterable<String> strings) { throw new UnsupportedOperationException(); } @Override public ParsedAppId parseFullAppId(String s) { throw new UnsupportedOperationException(); } }