From 50750cf7890bb6877f653708a4ca9b1f920501f8 Mon Sep 17 00:00:00 2001 From: Jeff Mesnil Date: Thu, 15 Jan 2026 10:25:46 +0100 Subject: [PATCH 1/2] feat: TCK SUT requires authentication Use a simple properties file with 1 user credential. This requires the TCK to be configured to use HTTP basic authentication in its .env): ``` A2A_AUTH_TYPE=basic A2A_AUTH_USERNAME=alice A2A_AUTH_PASSWORD=a2a-p4ssw0rd ```` Signed-off-by: Jeff Mesnil --- tck/pom.xml | 5 +++++ .../io/a2a/tck/server/AgentCardProducer.java | 17 +++++++++++++++++ tck/src/main/resources/application.properties | 6 ++++++ 3 files changed, 28 insertions(+) diff --git a/tck/pom.xml b/tck/pom.xml index 7b2db1b81..28a7fb9f9 100644 --- a/tck/pom.xml +++ b/tck/pom.xml @@ -42,6 +42,11 @@ jakarta.ws.rs jakarta.ws.rs-api + + io.quarkus + quarkus-elytron-security-properties-file + provided + diff --git a/tck/src/main/java/io/a2a/tck/server/AgentCardProducer.java b/tck/src/main/java/io/a2a/tck/server/AgentCardProducer.java index 571e2bb1f..760d7bb42 100644 --- a/tck/src/main/java/io/a2a/tck/server/AgentCardProducer.java +++ b/tck/src/main/java/io/a2a/tck/server/AgentCardProducer.java @@ -3,15 +3,19 @@ import java.util.Collections; import java.util.List; +import java.util.Map; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Produces; +import io.a2a.server.ExtendedAgentCard; import io.a2a.server.PublicAgentCard; import io.a2a.spec.AgentCapabilities; import io.a2a.spec.AgentCard; import io.a2a.spec.AgentInterface; import io.a2a.spec.AgentSkill; +import io.a2a.spec.HTTPAuthSecurityScheme; +import io.a2a.spec.OpenIdConnectSecurityScheme; import io.a2a.spec.TransportProtocol; @ApplicationScoped @@ -39,6 +43,11 @@ public AgentCard agentCard() { .streaming(true) .pushNotifications(true) .build()) + .securitySchemes(Map.of("acme", HTTPAuthSecurityScheme.builder() + .scheme("basic") + .build())) + .security(List.of(Map.of("acme", Collections.emptyList()))) + .supportsExtendedAgentCard(true) .defaultInputModes(Collections.singletonList("text")) .defaultOutputModes(Collections.singletonList("text")) .skills(Collections.singletonList(AgentSkill.builder() @@ -55,5 +64,13 @@ private static String getEnvOrDefault(String envVar, String defaultValue) { String value = System.getenv(envVar); return value == null || value.isBlank() ? defaultValue : value; } + + @Produces + @ExtendedAgentCard + public AgentCard extendedAgentCard() { + return AgentCard.builder(agentCard()) + //TODO what can we put in the extended agent card + .build(); + } } diff --git a/tck/src/main/resources/application.properties b/tck/src/main/resources/application.properties index b23747b00..d4888ed2c 100644 --- a/tck/src/main/resources/application.properties +++ b/tck/src/main/resources/application.properties @@ -19,3 +19,9 @@ quarkus.log.file.enable=true quarkus.log.file.path=target/tck-test.log quarkus.log.file.level=DEBUG quarkus.log.console.level=INFO + +# Enable basic authentication +quarkus.http.auth.basic=true +quarkus.security.users.embedded.enabled=true +quarkus.security.users.embedded.plain-text=true +quarkus.security.users.embedded.users.alice=a2a-p4ssw0rd \ No newline at end of file From 961fec4fe79d3999ad1bc85c18a2596a853fa54c Mon Sep 17 00:00:00 2001 From: Jeff Mesnil Date: Thu, 15 Jan 2026 16:48:26 +0100 Subject: [PATCH 2/2] chore: Run TCK with user authentication Signed-off-by: Jeff Mesnil --- .github/workflows/run-tck-1.0-wip.yml | 22 +++++++++++++------ .../io/a2a/tck/server/AgentCardProducer.java | 4 ++-- tck/src/main/resources/application.properties | 3 +-- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/.github/workflows/run-tck-1.0-wip.yml b/.github/workflows/run-tck-1.0-wip.yml index b29c78c2c..98dab52ae 100644 --- a/.github/workflows/run-tck-1.0-wip.yml +++ b/.github/workflows/run-tck-1.0-wip.yml @@ -5,9 +5,9 @@ on: push: branches: - main - #pull_request: - # branches: - # - main + pull_request: + branches: + - main workflow_dispatch: env: @@ -64,8 +64,12 @@ jobs: working-directory: tck/a2a-tck - name: Build with Maven, skipping tests run: mvn -B install -DskipTests + - name: Generate random password + run: | + A2A_PASSWORD=$(openssl rand -base64 16) + echo "A2A_PASSWORD=$A2A_PASSWORD" >> $GITHUB_ENV - name: Start SUT - run: SUT_GRPC_URL=${{ env.SUT_JSONRPC_URL }} SUT_REST_URL=${{ env.SUT_JSONRPC_URL }} mvn -B quarkus:dev & #SUT_JSONRPC_URL already set + run: SUT_GRPC_URL=${{ env.SUT_JSONRPC_URL }} SUT_REST_URL=${{ env.SUT_JSONRPC_URL }} mvn -B quarkus:dev -Dquarkus.security.users.embedded.users.alice=${A2A_PASSWORD} & working-directory: tck - name: Wait for SUT to start run: | @@ -101,12 +105,16 @@ jobs: sleep "$RETRY_INTERVAL" done - - name: Run TCK (JSONRPC) + - name: Run TCK id: run-tck - timeout-minutes: 5 + timeout-minutes: 10 run: | set -o pipefail - ./run_tck.py --sut-url ${{ env.SUT_JSONRPC_URL }} --category all --transports jsonrpc --compliance-report report.json 2>&1 | tee tck-output.log + export PYTHONUNBUFFERED=1 + A2A_AUTH_TYPE=basic \ + A2A_AUTH_USERNAME=alice \ + A2A_AUTH_PASSWORD=$A2A_PASSWORD \ + ./run_tck.py --sut-url ${{ env.SUT_JSONRPC_URL }} --category all --transports jsonrpc,grpc,rest --compliance-report report.json 2>&1 | tee tck-output.log working-directory: tck/a2a-tck - name: Capture Diagnostics on Failure if: failure() diff --git a/tck/src/main/java/io/a2a/tck/server/AgentCardProducer.java b/tck/src/main/java/io/a2a/tck/server/AgentCardProducer.java index 760d7bb42..fba892d8b 100644 --- a/tck/src/main/java/io/a2a/tck/server/AgentCardProducer.java +++ b/tck/src/main/java/io/a2a/tck/server/AgentCardProducer.java @@ -42,12 +42,12 @@ public AgentCard agentCard() { .capabilities(AgentCapabilities.builder() .streaming(true) .pushNotifications(true) + .extendedAgentCard(true) .build()) .securitySchemes(Map.of("acme", HTTPAuthSecurityScheme.builder() .scheme("basic") .build())) - .security(List.of(Map.of("acme", Collections.emptyList()))) - .supportsExtendedAgentCard(true) + .securityRequirements(List.of(Map.of("acme", Collections.emptyList()))) .defaultInputModes(Collections.singletonList("text")) .defaultOutputModes(Collections.singletonList("text")) .skills(Collections.singletonList(AgentSkill.builder() diff --git a/tck/src/main/resources/application.properties b/tck/src/main/resources/application.properties index d4888ed2c..245071012 100644 --- a/tck/src/main/resources/application.properties +++ b/tck/src/main/resources/application.properties @@ -23,5 +23,4 @@ quarkus.log.console.level=INFO # Enable basic authentication quarkus.http.auth.basic=true quarkus.security.users.embedded.enabled=true -quarkus.security.users.embedded.plain-text=true -quarkus.security.users.embedded.users.alice=a2a-p4ssw0rd \ No newline at end of file +quarkus.security.users.embedded.plain-text=true \ No newline at end of file