![](/img/trans.png)
[英]Default Credentials in Google App Engine: Invalid Credentials error
[英]Google Cloud Storage API cannot get Application Default Credentials on App Engine looking for Compute Engine error
我在Google App Engine而非Compute Engine上運行的Play(v2.5.12)應用程序中使用Google Cloud Storage API庫獲得了自定義代碼。 啟用了Cloud Storage API。 我正在嘗試將文件(作為文件流)發送到Google Cloud Platform中的存儲桶。
這是代碼:
public static String sendFileToBucket(InputStream fileStream, String fileName) throws IOException {
Logger.info("GoogleStorage: sendFileToBucket: Starting...");
Storage storage = StorageOptions.getDefaultInstance().getService();
// Modify access list to allow all users with link to read file
List<Acl> acls = new ArrayList<>();
acls.add(Acl.of(Acl.User.ofAllUsers(), Acl.Role.READER));
// the inputstream is closed by default, so we don't need to close it
// here
Blob blob = null;
blob = storage.create(BlobInfo.newBuilder(BUCKET_NAME, fileName).setAcl(acls).build(),
fileStream);
return blob.getMediaLink();
}
我編寫的代碼使用此示例:
https://cloud.google.com/appengine/docs/flexible/java/using-cloud-storage#application_code
嘗試設置Storage
對象時遇到錯誤:
Storage storage = StorageOptions.getDefaultInstance().getService();
這是完整的錯誤:
[warn] c.g.a.o.ComputeEngineCredentials - Failed to detect whether we are running on Google Compute Engine.
java.net.SocketException: Network is unreachable: connect
at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at sun.net.NetworkClient.doConnect(NetworkClient.java:175)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:432)
[warn] c.g.a.o.ComputeEngineCredentials - Failed to detect whether we are running on Google Compute Engine.
java.net.SocketException: Network is unreachable: connect
at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at sun.net.NetworkClient.doConnect(NetworkClient.java:175)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:432)
[warn] c.g.a.o.ComputeEngineCredentials - Failed to detect whether we are running on Google Compute Engine.
java.net.SocketException: Network is unreachable: connect
at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at sun.net.NetworkClient.doConnect(NetworkClient.java:175)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:432)
com.google.cloud.storage.StorageException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at com.google.cloud.storage.spi.v1.HttpStorageRpc.translate(HttpStorageRpc.java:220)
at com.google.cloud.storage.spi.v1.HttpStorageRpc.create(HttpStorageRpc.java:291)
at com.google.cloud.storage.StorageImpl.create(StorageImpl.java:148)
at google.GoogleStorage.sendFileToBucket(GoogleStorage.java:80)
at controllers.AdultPTPController.adultPTPUpdateFields(AdultPTPController.java:3878)
at controllers.AdultPTPController.adultPTPUpdate(AdultPTPController.java:3544)
at router.Routes$$anonfun$routes$1$$anonfun$applyOrElse$10$$anonfun$apply$10.apply(Routes.scala:2083)
at router.Routes$$anonfun$routes$1$$anonfun$applyOrElse$10$$anonfun$apply$10.apply(Routes.scala:2083)
at play.core.routing.HandlerInvokerFactory$$anon$4.resultCall(HandlerInvoker.scala:157)
at play.core.routing.HandlerInvokerFactory$$anon$4.resultCall(HandlerInvoker.scala:156)
at play.core.routing.HandlerInvokerFactory$JavaActionInvokerFactory$$anon$14$$anon$3$$anon$1.invocation(HandlerInvoker.scala:136)
at play.core.j.JavaAction$$anon$1.call(JavaAction.scala:73)
at play.http.HttpRequestHandler$1.call(HttpRequestHandler.java:54)
at play.core.j.JavaAction$$anonfun$7.apply(JavaAction.scala:108)
at play.core.j.JavaAction$$anonfun$7.apply(JavaAction.scala:108)
at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24)
at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24)
at play.core.j.HttpExecutionContext$$anon$2.run(HttpExecutionContext.scala:56)
at play.api.libs.iteratee.Execution$trampoline$.execute(Execution.scala:70)
at play.core.j.HttpExecutionContext.execute(HttpExecutionContext.scala:48)
at scala.concurrent.impl.Future$.apply(Future.scala:31)
at scala.concurrent.Future$.apply(Future.scala:492)
at play.core.j.JavaAction.apply(JavaAction.scala:108)
at play.api.mvc.Action$$anonfun$apply$2$$anonfun$apply$5$$anonfun$apply$6.apply(Action.scala:112)
at play.api.mvc.Action$$anonfun$apply$2$$anonfun$apply$5$$anonfun$apply$6.apply(Action.scala:112)
at play.utils.Threads$.withContextClassLoader(Threads.scala:21)
at play.api.mvc.Action$$anonfun$apply$2$$anonfun$apply$5.apply(Action.scala:111)
at play.api.mvc.Action$$anonfun$apply$2$$anonfun$apply$5.apply(Action.scala:110)
at scala.Option.map(Option.scala:146)
at play.api.mvc.Action$$anonfun$apply$2.apply(Action.scala:110)
at play.api.mvc.Action$$anonfun$apply$2.apply(Action.scala:103)
at scala.concurrent.Future$$anonfun$flatMap$1.apply(Future.scala:251)
at scala.concurrent.Future$$anonfun$flatMap$1.apply(Future.scala:249)
at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32)
at akka.dispatch.BatchingExecutor$AbstractBatch.processBatch(BatchingExecutor.scala:55)
at akka.dispatch.BatchingExecutor$BlockableBatch$$anonfun$run$1.apply$mcV$sp(BatchingExecutor.scala:91)
at akka.dispatch.BatchingExecutor$BlockableBatch$$anonfun$run$1.apply(BatchingExecutor.scala:91)
at akka.dispatch.BatchingExecutor$BlockableBatch$$anonfun$run$1.apply(BatchingExecutor.scala:91)
at scala.concurrent.BlockContext$.withBlockContext(BlockContext.scala:72)
at akka.dispatch.BatchingExecutor$BlockableBatch.run(BatchingExecutor.scala:90)
at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:39)
at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:415)
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1509)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:914)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream0(HttpURLConnection.java:1283)
at sun.net.www.protocol.http.HttpURLConnection.access$100(HttpURLConnection.java:90)
at sun.net.www.protocol.http.HttpURLConnection$8.run(HttpURLConnection.java:1250)
at sun.net.www.protocol.http.HttpURLConnection$8.run(HttpURLConnection.java:1248)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessController.doPrivilegedWithCombiner(AccessController.java:782)
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1247)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:250)
at com.google.api.client.http.javanet.NetHttpRequest.execute(NetHttpRequest.java:77)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:981)
at com.google.api.client.googleapis.media.MediaHttpUploader.executeCurrentRequestWithoutGZip(MediaHttpUploader.java:545)
at com.google.api.client.googleapis.media.MediaHttpUploader.executeCurrentRequest(MediaHttpUploader.java:562)
at com.google.api.client.googleapis.media.MediaHttpUploader.directUpload(MediaHttpUploader.java:360)
at com.google.api.client.googleapis.media.MediaHttpUploader.upload(MediaHttpUploader.java:334)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:428)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:352)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:469)
at com.google.cloud.storage.spi.v1.HttpStorageRpc.create(HttpStorageRpc.java:288)
... 44 more
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
at sun.security.validator.Validator.validate(Validator.java:260)
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1491)
... 71 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)
... 77 more
由於我在Google App Engine而不是Compute Engine上運行應用程序,因此該錯誤使我感到困惑。 我檢查了服務帳戶,但只有默認的App Engine帳戶和為Google Drive訪問創建的服務帳戶。
我正在使用此處所述的應用程序默認憑據:
https://cloud.google.com/docs/authentication/production
默認的App Engine服務帳戶沒有密鑰,但是會創建一個密鑰,然后嘗試以下代碼示例:
Storage storage = StorageOptions.newBuilder()
.setCredentials(ServiceAccountCredentials.fromStream(new FileInputStream("/path/to/my/key.json")))
.build()
.getService();
從此頁面:
https://github.com/GoogleCloudPlatform/google-cloud-java/blob/master/README.md#authentication
解決我的問題?
我發現了一些關於此的文章,但是我無法解釋如何在我的代碼中實現,因此它們沒有幫助我:
感謝您的幫助。
-------------------------編輯3/23/2018 ------------------- -------------
收到錯誤后:
java.io.IOException: The Application Default Credentials are not available. They are available if running in Google Compute Engine. Otherwise, the environment variable GOOGLE_APPLICATION_CREDENTIALS must be defined pointing to a file defining the credentials. See https://developers.google.com/accounts/docs/application-default-credentials for more information.
然后點擊鏈接,在該頁面上顯示:
If your application runs on Compute Engine, Kubernetes Engine, the App Engine flexible environment, or Cloud Functions, you don't need to create your own service account.
但是我正在使用App Engine flex環境,這使我感到困惑。
因此,我去了Google Cloud Project,選擇了IAM&Admin>服務帳戶,並為默認的App Engine服務帳戶創建了一個密鑰,下載並將代碼更改為:
public static String sendFileToBucket(InputStream fileStream, String fileName) throws IOException {
Logger.info("GoogleStorage: sendFileToBucket: Starting...");
GoogleCredential credential = null;
String credentialsFileName = "";
Storage storage = null;
Logger.info("GoogleStorage: authorize: Getting credentialsFileName path...");
credentialsFileName = Configuration.root().getString("google.storage.credentials.file");
Logger.info("GoogleStorage: authorize: credentialsFileName = " + credentialsFileName);
Logger.info("GoogleStorage: authorize: Setting InputStream...");
InputStream in = GoogleStorage.class.getClassLoader().getResourceAsStream(credentialsFileName);
if (in == null) {
Logger.info("GoogleStorage: authorize: InputStream is null");
}
Logger.info("GoogleStorage: authorize: InputStream set...");
storage = StorageOptions.newBuilder()
.setCredentials(ServiceAccountCredentials.fromStream(in))
.build()
.getService();
// Modify access list to allow all users with link to read file
List<Acl> acls = new ArrayList<>();
acls.add(Acl.of(Acl.User.ofAllUsers(), Acl.Role.READER));
// the inputstream is closed by default, so we don't need to close it
// here
Blob blob = null;
blob = storage.create(BlobInfo.newBuilder(BUCKET_NAME, fileName).setAcl(acls).build(),
fileStream);
return blob.getMediaLink();
}
我沒有收到原始錯誤,它確實建立了Storage
對象。 但是,當它嘗試構建Blob
對象時,我收到此錯誤:
[warn] c.g.a.c.h.HttpTransport - exception thrown while executing request
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
...
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
...
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
...
com.google.cloud.storage.StorageException: Error getting access token for service account:
...
Caused by: java.io.IOException: Error getting access token for service account:
...
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
...
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
...
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
...
我看到的是:
com.google.cloud.storage.StorageException: Error getting access token for service account
因此,我猜想它仍然帶有服務帳戶憑據。
嘗試直接獲取應用程序默認憑據怎么辦?
您能否嘗試以下方法:
GoogleCredentials applicationDefault = GoogleCredentials.getApplicationDefault();
if (applicationDefault.createScopedRequired()){
applicationDefault = applicationDefault.createScoped(Collections.singleton("https://www.googleapis.com/auth/devstorage.full_control"));
}
final Storage storage = StorageOptions.newBuilder()
.setCredentials(applicationDefault)
.build()
.getService();
另外,您使用的是AppEngine標准版還是彈性版?
我在Compute Engine上也遇到過類似的問題。 然后,我在環境上使用了靜態路徑來存儲所需的所有屬性。 這是我的變量類:
public class Variables(){
public Variables(){
if(!loaded)init();
}
final static Logger logger = Logger.getLogger(Variables.class);
static Properties prop = new Properties();
static InputStream input = null;
static boolean loaded = false;
private static void init(){
try{
logger.info("Loading properties for server . . . ");
//Do not change this path
input = new FileInputStream("/path-on-server/app-config.properties");
prop.load(input);
loaded = true;
}catch(Exception ex){
logger.error("Error while loading configuration file for server. . . ");
logger.error(ex.getMessage());
}
finally{
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static final String gcsClientId = getGCSClientId();
public static final String gcsClientEmail = getGCSClientEmail();
public static final String gcsPrivateKey = getGCSPrivateKey();
public static final String gcsPrivateKeyId = getGCSPrivateKeyId();
public static final String gcsProjectId = getGCSProjectId();
public static final String gcsBucketName = getGCSBucketName();
private static String getGCSClientId(){
if(!loaded)init();
return prop.getProperty("storageClientId");
}
private static String getGCSClientEmail(){
if(!loaded)init();
return prop.getProperty("storageClientEmail");
}
private static String getGCSPrivateKeyId(){
if(!loaded)init();
return prop.getProperty("storagePrivateKeyId");
}
private static String getGCSPrivateKey(){
if(!loaded)init();
return prop.getProperty("storagePrivateKey");
}
private static String getGCSProjectId(){
if(!loaded)init();
return prop.getProperty("storageProjectId");
}
private static String getGCSBucketName(){
if(!loaded)init();
return prop.getProperty("storageBucketName");
}
}
然后在我的Google Storage中使用變量類:
public class GoogleCloudStorage {
Variables variables = new Variables();
public GoogleCloudStorage() {
setDefaultStorageCredentials();
}
private static Storage storage = null;
private static String bucketName = null;
private static Credentials credentials = null;
private void setDefaultStorageCredentials() {
try {
this.bucketName = variables.gcsBucketName;
credentials = ServiceAccountCredentials.fromPkcs8(variables.gcsClientId, variables.gcsClientEmail,
variables.gcsPrivateKey, variables.gcsPrivateKeyId, null);
storage = StorageOptions.newBuilder()
.setCredentials(credentials)
.setProjectId(variables.gcsProjectId).build().getService();
} catch (Exception e) {
e.printStackTrace();
}
}
}
希望這可以幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.