1

我有一个简单的应用程序,它通过基于 HTTP 的google-api-services-logging. 我最初使用的是 gRPCcloud-logging库,但根本无法让它与 GraalVM 一起使用。但不幸的是,我也在为 HTTP 变体而苦苦挣扎。该代码在传统 Java VM 上执行时运行良好,但在运行本机映像时在运行时失败。

java.io.IOException: Error getting access token for service account: 400 Bad Request
POST https://oauth2.googleapis.com/token
{"error":"invalid_grant","error_description":"Invalid JWT: Failed audience check."}
    at com.google.auth.oauth2.ServiceAccountCredentials.refreshAccessToken(ServiceAccountCredentials.java:444)
    at com.google.auth.oauth2.OAuth2Credentials.refresh(OAuth2Credentials.java:157)
    at com.google.auth.oauth2.OAuth2Credentials.getRequestMetadata(OAuth2Credentials.java:145)
    at com.google.auth.oauth2.ServiceAccountCredentials.getRequestMetadata(ServiceAccountCredentials.java:603)
    at com.google.auth.http.HttpCredentialsAdapter.initialize(HttpCredentialsAdapter.java:91)
    at com.google.api.client.http.HttpRequestFactory.buildRequest(HttpRequestFactory.java:88)
    at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.buildHttpRequest(AbstractGoogleClientRequest.java:422)
    at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:541)
    at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:474)
    at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:591)
    ...
Caused by: com.google.api.client.http.HttpResponseException: 400 Bad Request
POST https://oauth2.googleapis.com/token
{"error":"invalid_grant","error_description":"Invalid JWT: Failed audience check."}
    at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1113)
    at com.google.auth.oauth2.ServiceAccountCredentials.refreshAccessToken(ServiceAccountCredentials.java:441)
    ... 35 more

本机图像属性

Args = \
  --verbose \
  --no-server \
  --no-fallback \
  --static \
  --install-exit-handlers \
  -H:+ReportExceptionStackTraces \
  -H:+TraceClassInitialization \
  -H:+PrintClassInitialization \
  -H:UseMuslC=/musl/ \
  -H:+RemoveSaturatedTypeFlows \
  --enable-https \
  --enable-http \
  --initialize-at-build-time

反射配置.json

[
  {
    "name": "com.google.api.client.json.GenericJson",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true
  },
  {
    "name": "com.google.api.services.logging.v2.model.LogEntry",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true
  },
  {
    "name": "com.google.api.client.googleapis.GoogleUtils",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true
  }
]

资源配置.json

{
  "resources": [
    { "pattern": "^.*\\.json$" },
    { "pattern": "^.*\\.properties$" },
    { "pattern": "^.*\\.jks$" }
  ]
}

应用程序.scala

val scopes = util.Arrays.asList(LoggingScopes.CLOUD_PLATFORM_READ_ONLY, LoggingScopes.LOGGING_WRITE)
val credentials  = ServiceAccountCredentials.fromStream("service-account.json").createScoped(scopes)
val logging = new Logging.Builder(
  transport,
  JacksonFactory.getDefaultInstance,
  new HttpCredentialsAdapter(credentials)
).setApplicationName("my-project").build()

Dockerfile

FROM        oracle/graalvm-ce:20.1.0-java11 as builder
...
RUN         gu install native-image
...
RUN         sbt assembly
RUN         native-image -jar /root/target/scala-2.13/graal-test-assembly-0.1.0-SNAPSHOT.jar

FROM        scratch

WORKDIR     /app/

COPY        --from=builder /root/graal-test-assembly-0.1.0-SNAPSHOT /app/my-native-image

CMD         ["/app/my-native-image"]

我怀疑这与加密/ SSL 相关功能有关,但我没有东西可以尝试。

4

1 回答 1

4

事实证明,生成的 JWT 令牌基本上是空的,因为在序列化为 JSON 时会通过反射遍历字段。添加相应的规则来reflect-config.json解决该问题并揭示可以通过配置解决的更多问题。

[
  {
    "name": "com.google.api.client.json.GenericJson",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true
  },
  {
    "name": "com.google.api.client.json.webtoken.JsonWebToken",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true
  },
  {
    "name": "com.google.api.client.json.webtoken.JsonWebToken$Header",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true
  },
  {
    "name": "com.google.api.client.json.webtoken.JsonWebToken$Payload",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true
  },
  {
    "name": "com.google.api.client.util.GenericData",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true
  },
  {
    "name": "com.google.api.client.http.UrlEncodedContent",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true
  },
  {
    "name": "com.google.api.client.json.webtoken.JsonWebSignature$Header",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true
  },
  {
    "name": "com.google.api.client.json.webtoken.JsonWebSignature",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true
  },
  {
    "name": "com.google.api.services.logging.v2.model.WriteLogEntriesRequest",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true
  },
  {
    "name": "com.google.api.services.logging.v2.model.WriteLogEntriesResponse",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true
  },
  {
    "name": "com.google.api.services.logging.v2.model.LogEntry",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true
  },
  {
    "name": "com.google.api.client.googleapis.json.GoogleJsonError",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true
  },
  {
    "name": "com.google.api.services.logging.v2.model.MonitoredResource",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true
  }
]

在 Google 的 Java 库中滥用反射是相当痛苦的。他们至少可以将 GraalVM 本机映像配置添加到他们的库中。

您可以在此处找到用于 google cloud logging http 的完整 reflect-config.json 。

于 2020-07-26T15:10:04.400 回答