You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用GCP私有CA创建证书时遇ALPN协商失败问题求助

解决Google Cloud私有CA创建时的ALPN协议协商失败问题

问题现象

运行创建Google Cloud私有证书颁发机构(CA)的Java代码时,抛出以下错误:

Caused by: io.grpc.StatusRuntimeException: UNAVAILABLE: Failed ALPN negotiation: Unable to find compatible protocol
通道管道:[SslHandler#0, ProtocolNegotiators$ClientTlsHandler#0, WriteBufferingAndExceptionHandler#0, DefaultChannelPipeline$TailContext#0]

相关代码与配置

Java代码

/*
 * Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.demo.certificate;

import java.io.IOException;
import java.util.concurrent.ExecutionException;

// [START privateca_create_ca]

import com.google.api.core.ApiFuture;
import com.google.cloud.security.privateca.v1.CaPoolName;
import com.google.cloud.security.privateca.v1.CertificateAuthority;
import com.google.cloud.security.privateca.v1.CertificateAuthority.KeyVersionSpec;
import com.google.cloud.security.privateca.v1.CertificateAuthority.SignHashAlgorithm;
import com.google.cloud.security.privateca.v1.CertificateAuthorityServiceClient;
import com.google.cloud.security.privateca.v1.CertificateConfig;
import com.google.cloud.security.privateca.v1.CertificateConfig.SubjectConfig;
import com.google.cloud.security.privateca.v1.CreateCertificateAuthorityRequest;
import com.google.cloud.security.privateca.v1.KeyUsage;
import com.google.cloud.security.privateca.v1.KeyUsage.KeyUsageOptions;
import com.google.cloud.security.privateca.v1.Subject;
import com.google.cloud.security.privateca.v1.X509Parameters;
import com.google.cloud.security.privateca.v1.X509Parameters.CaOptions;
import com.google.longrunning.Operation;
import com.google.protobuf.Duration;

public class CreateCertificateAuthority {

  public static void main(String[] args)
      throws InterruptedException, ExecutionException, IOException {
    // TODO(developer): Replace these variables before running the sample.
    // location: For a list of locations, see:
    // https://cloud.google.com/certificate-authority-service/docs/locations
    // poolId: Set it to the CA Pool under which the CA should be created.
    // certificateAuthorityName: Unique name for the CA.
    String project = "corp-esgda-dev";
    String location = "us-east1";
    String poolId = "test-pool";
    String certificateAuthorityName = "myCA";
    createCertificateAuthority(project, location, poolId, certificateAuthorityName);
  }

  // Create Certificate Authority which is the root CA in the given CA Pool.
  public static void createCertificateAuthority(
      String project, String location, String poolId, String certificateAuthorityName)
      throws InterruptedException, ExecutionException, IOException {
    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests. After completing all of your requests, call
    // the `certificateAuthorityServiceClient.close()` method on the client to safely
    // clean up any remaining background resources.
    try (CertificateAuthorityServiceClient certificateAuthorityServiceClient =
        CertificateAuthorityServiceClient.create()) {
    
        
        System.setProperty("https.protocols", "TLSv1.2");
        System.out.println(System.getProperties());
      String commonName = "dev";
      String orgName = "qc";
      int caDuration = 100000; // Validity of this CA in seconds.
      
      
     
      // Set the type of Algorithm.
      KeyVersionSpec keyVersionSpec =
          KeyVersionSpec.newBuilder().setAlgorithm(SignHashAlgorithm.RSA_PKCS1_4096_SHA256).build();

      // Set CA subject config.
      SubjectConfig subjectConfig =
          SubjectConfig.newBuilder()
              .setSubject(
                  Subject.newBuilder().setCommonName(commonName).setOrganization(orgName).build())
              .build();

      //  Set the key usage options for X.509 fields.
      X509Parameters x509Parameters =
          X509Parameters.newBuilder()
              .setKeyUsage(
                  KeyUsage.newBuilder()
                      .setBaseKeyUsage(
                          KeyUsageOptions.newBuilder().setCrlSign(true).setCertSign(true).build())
                      .build())
              .setCaOptions(CaOptions.newBuilder().setIsCa(true).build())
              .build();

      // Set certificate authority settings.
      CertificateAuthority certificateAuthority =
          CertificateAuthority.newBuilder()
              // CertificateAuthority.Type.SELF_SIGNED denotes that this CA is a root CA.
              .setType(CertificateAuthority.Type.SELF_SIGNED)
              .setKeySpec(keyVersionSpec)
              .setConfig(
                  CertificateConfig.newBuilder()
                      .setSubjectConfig(subjectConfig)
                      .setX509Config(x509Parameters)
                      .build())
              // Set the CA validity duration.
              .setLifetime(Duration.newBuilder().setSeconds(caDuration).build())
              .build();

      // Create the CertificateAuthorityRequest.
      CreateCertificateAuthorityRequest certificateAuthorityRequest =
          CreateCertificateAuthorityRequest.newBuilder()
              .setParent(CaPoolName.of(project, location, poolId).toString())
              .setCertificateAuthorityId(certificateAuthorityName)
              .setCertificateAuthority(certificateAuthority)
              .build();

      // Create Certificate Authority.
      ApiFuture<Operation> futureCall =
          certificateAuthorityServiceClient
              .createCertificateAuthorityCallable()
              .futureCall(certificateAuthorityRequest);
      System.out.println("futureCall:"+futureCall);
      Operation response = futureCall.get();

      if (response.hasError()) {
        System.out.println("Error while creating CA !" + response.getError());
        return;
      }

      System.out.println(
          "Certificate Authority created successfully : " + certificateAuthorityName);
    }
  }
}
// [END privateca_create_ca]

Maven Pom.xml配置

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>certificate</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>certificate-demo</name>

    <properties>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.compiler.source>1.8</maven.compiler.source>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.google.cloud</groupId>
                <artifactId>libraries-bom</artifactId>
                <version>26.29.0</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>com.google.cloud</groupId>
            <artifactId>google-cloud-security-private-ca</artifactId>
        </dependency>
        <dependency>
            <groupId>com.google.cloud</groupId>
            <artifactId>google-cloud-monitoring</artifactId>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-alpn-openjdk8-client</artifactId>
            <version>9.4.44.v20210927</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.6</version> <!-- Use the latest version available -->
        </dependency>


        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcpkix-jdk15on</artifactId>
            <version>1.70</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.google.truth</groupId>
            <artifactId>truth</artifactId>
            <version>1.2.0</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

解决方案

1. 调整系统属性设置时机

将TLS协议配置移到main方法最开头,确保在客户端初始化前生效,同时添加gRPC SSL提供者配置:

public static void main(String[] args)
    throws InterruptedException, ExecutionException, IOException {
  // 提前设置TLS协议与gRPC SSL提供者,确保在客户端初始化前生效
  System.setProperty("https.protocols", "TLSv1.2");
  System.setProperty("grpc.ssl.provider", "openjdk");
  
  String project = "corp-esgda-dev";
  String location = "us-east1";
  String poolId = "test-pool";
  String certificateAuthorityName = "myCA";
  createCertificateAuthority(project, location, poolId, certificateAuthorityName);
}

2. 清理冲突依赖

移除jetty-alpn-openjdk8-client依赖,因为Google Cloud的gRPC客户端依赖已经包含适配Java 8的ALPN支持,手动添加该依赖会导致版本冲突。修改后的dependencies部分如下:

<dependencies>
    <dependency>
        <groupId>com.google.cloud</groupId>
        <artifactId>google-cloud-security-private-ca</artifactId>
    </dependency>
    <dependency>
        <groupId>com.google.cloud</groupId>
        <artifactId>google-cloud-monitoring</artifactId>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.2.6</version>
    </dependency>

    <!-- 测试依赖保留 -->
    <dependency>
        <groupId>org.bouncycastle</groupId>
        <artifactId>bcpkix-jdk15on</artifactId>
        <version>1.70</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13.2</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>com.google.truth</groupId>
        <artifactId>truth</artifactId>
        <version>1.2.0</version>
        <scope>test</scope>
    </dependency>
</dependencies>

3. 验证JDK版本

确保运行环境使用Oracle JDK 8u251+或OpenJDK 8u252+,这些版本开始内置ALPN支持,无需额外配置。若使用旧版JDK 8,需手动添加ALPN的bootclasspath参数,但推荐直接升级JDK版本简化配置。

问题根源

Java 8默认缺少ALPN(应用层协议协商)支持,而gRPC与Google Cloud服务通信依赖HTTP/2协议,ALPN是HTTP/2握手的必要环节。当客户端无法协商出兼容协议时,就会触发Failed ALPN negotiation错误。通过调整依赖和系统属性,确保客户端正确支持TLS 1.2与ALPN,即可解决该问题。

内容的提问来源于stack exchange,提问作者Kiran

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 00:47:02