Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/trigger_files/beam_PostCommit_XVR_Direct.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"modification": 1,
"modification": 2,
"https://github.com/apache/beam/pull/39990": "removing dead code from FnApiDoFnRunner"
}
5 changes: 2 additions & 3 deletions .github/trigger_files/beam_PostCommit_XVR_Flink.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
{
"modification": 3,
"trigger-2026-04-04": "portable_runner expand_sdf opt-in",
"https://github.com/apache/beam/pull/39990": "removing dead code from FnApiDoFnRunner"
"modification": 4,
"trigger-2026-04-04": "portable_runner expand_sdf opt-in"
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
{
"comment": "Modify this file in a trivial way to cause this test suite to run.",
"modification": 1,
"https://github.com/apache/beam/pull/39990": "removing dead code from FnApiDoFnRunner"
"comment": "Modify this file in a trivial way to cause this test suite to run.",
"modification": 2
}
4 changes: 2 additions & 2 deletions .github/trigger_files/beam_PostCommit_XVR_Spark3.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"trigger-2026-07-08": "portable_runner expand_sdf opt-in 2",
"https://github.com/apache/beam/pull/39990": "removing dead code from FnApiDoFnRunner"
"modification": 1,
"trigger-2026-07-08": "portable_runner expand_sdf opt-in 2"
}
Original file line number Diff line number Diff line change
Expand Up @@ -803,6 +803,7 @@ class BeamModulePlugin implements Plugin<Project> {
grpc_google_cloud_pubsub_v1 : "com.google.api.grpc:grpc-google-cloud-pubsub-v1", // google_cloud_platform_libraries_bom sets version
grpc_google_common_protos : "com.google.api.grpc:grpc-google-common-protos", // google_cloud_platform_libraries_bom sets version
grpc_grpclb : "io.grpc:grpc-grpclb", // google_cloud_platform_libraries_bom sets version
grpc_inprocess : "io.grpc:grpc-inprocess", // google_cloud_platform_libraries_bom sets version
grpc_protobuf : "io.grpc:grpc-protobuf", // google_cloud_platform_libraries_bom sets version
grpc_protobuf_lite : "io.grpc:grpc-protobuf-lite", // google_cloud_platform_libraries_bom sets version
grpc_netty : "io.grpc:grpc-netty", // google_cloud_platform_libraries_bom sets version
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,9 @@
<!-- gRPC/protobuf exceptions -->
<!-- Non-vendored gRPC/protobuf imports are allowed for files that depend on libraries that expose gRPC/protobuf in its public API -->
<suppress id="ForbidNonVendoredGrpcProtobuf" files=".*sdk.*extensions.*protobuf.*" />
<suppress id="ForbidNonVendoredGrpcProtobuf" files=".*sdk.*core.*GcpHsmGeneratedSecret.*" />
<suppress id="ForbidNonVendoredGrpcProtobuf" files=".*sdk.*core.*GroupByEncryptedKeyTest.*" />
<suppress id="ForbidNonVendoredGrpcProtobuf" files=".*sdk.*core.*GroupByKeyTest.*" />
<suppress id="ForbidNonVendoredGrpcProtobuf" files=".*sdk.*core.*GroupByKeyIT.*" />
<suppress id="ForbidNonVendoredGrpcProtobuf" files=".*sdk.*core.*ValidateRunnerXlangTest.*" />
<suppress id="ForbidNonVendoredGrpcProtobuf" files=".*sdk.*extensions.*gcp.*GcpHsmGeneratedSecret.*" />
<suppress id="ForbidNonVendoredGrpcProtobuf" files=".*sdk.*extensions.*gcp.*GcpGroupByEncryptedKeyTest.*" />
<suppress id="ForbidNonVendoredGrpcProtobuf" files=".*sdk.*extensions.*gcp.*GcpGroupByKeyIT.*" />
<suppress id="ForbidNonVendoredGrpcProtobuf" files=".*sdk.*extensions.*ml.*" />
<suppress id="ForbidNonVendoredGrpcProtobuf" files=".*sdk.*io.*components.*ratelimiter.*" />
<suppress id="ForbidNonVendoredGrpcProtobuf" files=".*sdk.*io.*gcp.*" />
Expand Down
13 changes: 0 additions & 13 deletions sdks/java/core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -102,15 +102,6 @@ dependencies {
shadow library.java.slf4j_api
shadow library.java.snappy_java
shadow library.java.joda_time
implementation enforcedPlatform(library.java.google_cloud_platform_libraries_bom)
implementation library.java.gax
implementation library.java.google_cloud_kms
implementation library.java.proto_google_cloud_kms_v1
implementation library.java.google_cloud_tink
implementation library.java.google_cloud_secret_manager
implementation library.java.proto_google_cloud_secret_manager_v1
implementation library.java.protobuf_java
permitUnusedDeclared enforcedPlatform(library.java.google_cloud_platform_libraries_bom)
provided library.java.json_org
implementation library.java.everit_json_schema
implementation library.java.guava
Expand All @@ -133,10 +124,6 @@ dependencies {
shadowTest library.java.log4j
shadowTest library.java.log4j2_api
shadowTest library.java.jamm
shadowTest enforcedPlatform(library.java.google_cloud_platform_libraries_bom)
shadowTest library.java.google_cloud_secret_manager
shadowTest library.java.google_cloud_kms
shadowTest library.java.google_cloud_tink
testRuntimeOnly library.java.slf4j_jdk14
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,11 @@
*/
package org.apache.beam.sdk.transforms;

import static org.junit.Assert.assertThrows;

import com.google.cloud.secretmanager.v1.ProjectName;
import com.google.cloud.secretmanager.v1.SecretManagerServiceClient;
import com.google.cloud.secretmanager.v1.SecretName;
import com.google.cloud.secretmanager.v1.SecretPayload;
import com.google.protobuf.ByteString;
import java.io.IOException;
import java.io.Serializable;
import java.nio.charset.Charset;
import java.security.SecureRandom;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
Expand All @@ -39,14 +32,11 @@
import org.apache.beam.sdk.testing.NeedsRunner;
import org.apache.beam.sdk.testing.PAssert;
import org.apache.beam.sdk.testing.TestPipeline;
import org.apache.beam.sdk.util.GcpHsmGeneratedSecret;
import org.apache.beam.sdk.util.GcpSecret;
import org.apache.beam.sdk.util.RawSecret;
import org.apache.beam.sdk.util.Secret;
import org.apache.beam.sdk.values.KV;
import org.apache.beam.sdk.values.PCollection;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.categories.Category;
Expand Down Expand Up @@ -100,138 +90,9 @@ public void testGroupByKeyFakeSecret() {
p.run();
}

private static final String PROJECT_ID = "apache-beam-testing";
private static final String SECRET_ID = "gbek-test";
private static Secret gcpSecret;
private static Secret gcpHsmGeneratedSecret;
private static final String KEY_RING_ID = "gbek-test-key-ring";
private static final String KEY_ID = "gbek-test-key";

@BeforeClass
public static void setup() throws IOException {
SecretManagerServiceClient client = SecretManagerServiceClient.create();
ProjectName projectName = ProjectName.of(PROJECT_ID);
SecretName secretName = SecretName.of(PROJECT_ID, SECRET_ID);

try {
client.getSecret(secretName);
} catch (Exception e) {
com.google.cloud.secretmanager.v1.Secret secret =
com.google.cloud.secretmanager.v1.Secret.newBuilder()
.setReplication(
com.google.cloud.secretmanager.v1.Replication.newBuilder()
.setAutomatic(
com.google.cloud.secretmanager.v1.Replication.Automatic.newBuilder()
.build())
.build())
.build();
client.createSecret(projectName, SECRET_ID, secret);
byte[] secretBytes = new byte[32];
new SecureRandom().nextBytes(secretBytes);
client.addSecretVersion(
secretName,
SecretPayload.newBuilder()
.setData(ByteString.copyFrom(java.util.Base64.getUrlEncoder().encode(secretBytes)))
.build());
}
gcpSecret = new GcpSecret(secretName.toString() + "/versions/latest");

try {
com.google.cloud.kms.v1.KeyManagementServiceClient kmsClient =
com.google.cloud.kms.v1.KeyManagementServiceClient.create();
String locationId = "global";
com.google.cloud.kms.v1.KeyRingName keyRingName =
com.google.cloud.kms.v1.KeyRingName.of(PROJECT_ID, locationId, KEY_RING_ID);
com.google.cloud.kms.v1.LocationName locationName =
com.google.cloud.kms.v1.LocationName.of(PROJECT_ID, locationId);
try {
kmsClient.getKeyRing(keyRingName);
} catch (Exception e) {
kmsClient.createKeyRing(
locationName, KEY_RING_ID, com.google.cloud.kms.v1.KeyRing.newBuilder().build());
}

com.google.cloud.kms.v1.CryptoKeyName keyName =
com.google.cloud.kms.v1.CryptoKeyName.of(PROJECT_ID, locationId, KEY_RING_ID, KEY_ID);
try {
kmsClient.getCryptoKey(keyName);
} catch (Exception e) {
com.google.cloud.kms.v1.CryptoKey key =
com.google.cloud.kms.v1.CryptoKey.newBuilder()
.setPurpose(com.google.cloud.kms.v1.CryptoKey.CryptoKeyPurpose.ENCRYPT_DECRYPT)
.build();
kmsClient.createCryptoKey(keyRingName, KEY_ID, key);
}
gcpHsmGeneratedSecret =
new GcpHsmGeneratedSecret(
PROJECT_ID,
locationId,
KEY_RING_ID,
KEY_ID,
String.format("gbek-test-job-%d", new SecureRandom().nextInt(10000)));
// Validate we have crypto permissions or skip these tests.
gcpHsmGeneratedSecret.getSecretBytes();
} catch (Exception e) {
gcpHsmGeneratedSecret = null;
}
}

@AfterClass
public static void tearDown() throws IOException {
SecretManagerServiceClient client = SecretManagerServiceClient.create();
SecretName secretName = SecretName.of(PROJECT_ID, SECRET_ID);
client.deleteSecret(secretName);
}

@Test
@Category(NeedsRunner.class)
public void testGroupByKeyGcpSecret() {
List<KV<@Nullable String, Integer>> ungroupedPairs =
Arrays.asList(
KV.of(null, 3),
KV.of("k1", 3),
KV.of("k5", Integer.MAX_VALUE),
KV.of("k5", Integer.MIN_VALUE),
KV.of("k2", 66),
KV.of("k1", 4),
KV.of(null, 5),
KV.of("k2", -33),
KV.of("k3", 0));

PCollection<KV<String, Integer>> input =
p.apply(
Create.of(ungroupedPairs)
.withCoder(KvCoder.of(NullableCoder.of(StringUtf8Coder.of()), VarIntCoder.of())));

PCollection<KV<String, Iterable<Integer>>> output =
input.apply(GroupByEncryptedKey.<String, Integer>create(gcpSecret));

PAssert.that(output.apply("Sort", MapElements.via(new SortValues())))
.containsInAnyOrder(
KV.of("k1", Arrays.asList(3, 4)),
KV.of(null, Arrays.asList(3, 5)),
KV.of("k5", Arrays.asList(Integer.MIN_VALUE, Integer.MAX_VALUE)),
KV.of("k2", Arrays.asList(-33, 66)),
KV.of("k3", Arrays.asList(0)));

p.run();
}

@Test
@Category(NeedsRunner.class)
public void testGroupByKeyGcpSecretThrows() {
Secret gcpSecret = new GcpSecret("bad_path/versions/latest");
p.apply(Create.of(KV.of("k1", 1)))
.apply(GroupByEncryptedKey.<String, Integer>create(gcpSecret));
assertThrows(RuntimeException.class, () -> p.run());
}

@Test
@Category(NeedsRunner.class)
public void testGroupByKeyGcpHsmGeneratedSecret() {
if (gcpHsmGeneratedSecret == null) {
return;
}
public void testGroupByKeyRawSecret() {
List<KV<@Nullable String, Integer>> ungroupedPairs =
Arrays.asList(
KV.of(null, 3),
Expand All @@ -249,8 +110,12 @@ public void testGroupByKeyGcpHsmGeneratedSecret() {
Create.of(ungroupedPairs)
.withCoder(KvCoder.of(NullableCoder.of(StringUtf8Coder.of()), VarIntCoder.of())));

// GroupByEncryptedKey expects Secret#getSecretBytes() to return Base64-URL encoded
// bytes of a valid AES key (e.g. 32 bytes for AES-256).
byte[] secretBytes = "test-encryption-key-secret-12345".getBytes(StandardCharsets.UTF_8);
Secret rawSecret = new RawSecret(Base64.getUrlEncoder().encode(secretBytes));
PCollection<KV<String, Iterable<Integer>>> output =
input.apply(GroupByEncryptedKey.<String, Integer>create(gcpHsmGeneratedSecret));
input.apply(GroupByEncryptedKey.<String, Integer>create(rawSecret));

PAssert.that(output.apply("Sort", MapElements.via(new SortValues())))
.containsInAnyOrder(
Expand Down
Loading
Loading