通过服务访问密钥对Google计算引擎进行编程验证



研究Google Compute文档后,我发现没有通过生成的服务访问密钥进行身份验证的示例。

我尝试使用以下代码(这是第69行(

GoogleCredential credential = new GoogleCredential.Builder()
                .setClientSecrets(authorize())
                .build();

private static  GoogleClientSecrets authorize() {
    // initialize client secrets object
    GoogleClientSecrets clientSecrets;
    // load client secrets
    try {
        clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(
                GCEImporter.class.getResourceAsStream("/client_secrets.json")));
    } catch(IOException e){
        e.printStackTrace();
        return null;
    }

    return clientSecrets;
}

client_secrets.json是Google的生成文件,看起来像

{
 "type": "service_account",
 "project_id": "...",
 "private_key_id": "...",
 "private_key": "-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----n",
 "client_email": "....iam.gserviceaccount.com",
 "client_id": "...",
 "auth_uri": "https://accounts.google.com/o/oauth2/auth",
 "token_uri": "https://accounts.google.com/o/oauth2/token",
 "auth_provider_x509_cert_url": 
 "https://www.googleapis.com/oauth2/v1/certs",
 "client_x509_cert_url": 
 "https://www.googleapis.com/robot/v1/metadata/x509/..."
}

执行此代码时我会收到的一切

java.lang.IllegalArgumentException
at com.google.api.client.repackaged.com.google.common.base.Preconditions.checkArgument(Preconditions.java:111)
at com.google.api.client.util.Preconditions.checkArgument(Preconditions.java:37)
at com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets.getDetails(GoogleClientSecrets.java:82)
at com.google.api.client.googleapis.auth.oauth2.GoogleCredential$Builder.setClientSecrets(GoogleCredential.java:559)
at net.bytesource.jira.asset.synchronization.importer.google.gce.GCEImporter.getAssets(GCEImporter.java:69)
at net.bytesource.jira.asset.synchronization.importer.google.gce.GoogleImporterTest.getAssets(GoogleImporterTest.java:33)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

有人可以解决这个问题吗?

感谢您的回答Tuxdude。我还通过复制网站的示例提前尝试了您的方式。但这只能在GCE环境中的实例中起作用。

我自己找到了解决方案,这是GoogleCredential类的静态方法:

GoogleCredential.fromStream(new FileInputStreamReader("path/to/json"))

这里几乎没有问题:

  • 您从IAM页面创建新的服务帐户时下载的私钥信息JSON文件不在客户端秘密期望的格式中。

  • 您正在尝试遵循[OAuth steps that are meant for Desktop and mobile apps][2]。这将无法与Google Cloud Apis一起使用。

推荐,更简单的授权使用Google Cloud API是使用应用程序默认凭据,此处和此处描述。

简而言之,您需要做的是(基于此处的轮廓(:

  1. 设置您在环境中拥有的JSON文件的路径变量GOOGLE_APPLICATION_CREDENTIALS

  2. 创建GoogleCredential对象,如下所示。

GoogleCredential credential = GoogleCredential.getApplicationDefault();

在上述步骤之后,您应该能够与任何Google Cloud API进行交谈。如果GCE,您将创建一个Compute

的实例

Compute compute = new Compute.Builder (transport, jsonFactory, credential).build();

我只是从compute.instances.insert api复制并粘贴示例。

/*
 * BEFORE RUNNING:
 * ---------------
 * 1. If not already done, enable the Compute Engine API
 *    and check the quota for your project at
 *    https://console.developers.google.com/apis/api/compute
 * 2. This sample uses Application Default Credentials for authentication.
 *    If not already done, install the gcloud CLI from
 *    https://cloud.google.com/sdk and run
 *    `gcloud beta auth application-default login`.
 *    For more information, see
 *    https://developers.google.com/identity/protocols/application-default-credentials
 * 3. Install the Java client library on Maven or Gradle. Check installation
 *    instructions at https://github.com/google/google-api-java-client.
 *    On other build systems, you can add the jar files to your project from
 *    https://developers.google.com/resources/api-libraries/download/compute/v1/java
 */
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.compute.Compute;
import com.google.api.services.compute.model.Instance;
import com.google.api.services.compute.model.Operation;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Arrays;
public class ComputeExample {
  public static void main(String args[]) throws IOException, GeneralSecurityException {
    // Project ID for this request.
    String project = ""; // TODO: Update placeholder value.
    // The name of the zone for this request.
    String zone = ""; // TODO: Update placeholder value.
    // TODO: Assign values to desired fields of `requestBody`:
    Instance requestBody = new Instance();
    Compute computeService = createComputeService();
    Compute.Instances.Insert request =
        computeService.instances().insert(project, zone, requestBody);
    Operation response = request.execute();
    // TODO: Change code below to process the `response` object:
    System.out.println(response);
  }
  public static Compute createComputeService() throws IOException, GeneralSecurityException {
    HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
    JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
    GoogleCredential credential = GoogleCredential.getApplicationDefault();
    if (credential.createScopedRequired()) {
      credential =
          credential.createScoped(Arrays.asList("https://www.googleapis.com/auth/cloud-platform"));
    }
    return new Compute.Builder(httpTransport, jsonFactory, credential)
        .setApplicationName("Google-ComputeSample/0.1")
        .build();
  }
}

最新更新