alts: AuthorizationUtil.clientAuthorizationCheck compares the peer service account case-sensitively

Aperta Adatta ai principianti
#13,156 1 commento 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
85/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
java
Ambito
authorization

Direzione di ricerca

Il confronto si trova in clientAuthorizationCheck in alts/src/main/java/io/grpc/alts/AuthorizationUtil.java, che attualmente usa Collection.contains, un test di corrispondenza esatta. Leggi quel metodo e il AuthorizationUtilTest esistente, quindi aggiungi il caso di test di regressione senza distinzione tra maiuscole e minuscole descritto nell'issue. È completato quando il nuovo test passa, i test esistenti continuano a passare con ./gradlew :grpc-alts:test e il Javadoc indica la corrispondenza senza distinzione tra maiuscole e minuscole.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

alts: AuthorizationUtil.clientAuthorizationCheck compares the peer service account case-sensitively


**正文(Markdown 原文)**

`````markdown
### What version of gRPC-Java are you using?

`master` at [`15d64a4`](https://github.com/grpc/grpc-java/commit/15d64a4678450991aa5bf7af23066d36b3391351) (`1.86.0-SNAPSHOT`); `AuthorizationUtil` is unchanged on current `master`.

### What is your environment?

Linux x86_64, OpenJDK 21.0.2, Gradle 8.14.5 (wrapper).

### What did you expect to see?

`AuthorizationUtil.clientAuthorizationCheck(call, expectedServiceAccounts)` accepts a client whose ALTS peer service account differs from an allowed entry only in letter case (for example peer `alice`, allowed `ALICE`), as grpc-go's equivalent `alts.ClientAuthorizationCheck` does.

### What did you see instead?

It returns `PERMISSION_DENIED` ("Client alice is not authorized").

**Location** (`grpc/grpc-java` @ `15d64a4`):

- [`alts/src/main/java/io/grpc/alts/AuthorizationUtil.java:35-47`](https://github.com/grpc/grpc-java/blob/15d64a4678450991aa5bf7af23066d36b3391351/alts/src/main/java/io/grpc/alts/AuthorizationUtil.java#L35-L47)

```java
  public static Status clientAuthorizationCheck(
      ServerCall<?, ?> call, Collection<String> expectedServiceAccounts) {
    ...
    if (expectedServiceAccounts.contains(altsContext.getPeerServiceAccount())) {
      return Status.OK;
    }
    return Status.PERMISSION_DENIED.withDescription(
        "Client " + altsContext.getPeerServiceAccount() + " is not authorized");
  }

Problem

Collection.contains() uses String.equals(), so the check is exact-match. Service account identifiers are e-mail style names that people often write in mixed case in config. grpc-go changed its helper for exactly this reason ("expectedServiceAccounts are commonly mixed-case, while the PeerServiceAccount is lower-case"). With the Java helper, an allow-list entry that differs only in case rejects a legitimate client, and the two languages give different answers for the same allow-list. This only concerns letter case; any other difference in the name is still rejected.

Steps to reproduce the bug

Reproduction

Regression test added to AuthorizationUtilTest (reuses its FakeServerCall, which sets the ALTS peer service account):

diff --git a/alts/src/test/java/io/grpc/alts/AuthorizationUtilTest.java b/alts/src/test/java/io/grpc/alts/AuthorizationUtilTest.java
--- a/alts/src/test/java/io/grpc/alts/AuthorizationUtilTest.java
+++ b/alts/src/test/java/io/grpc/alts/AuthorizationUtilTest.java
@@ -55,6 +55,14 @@ public final class AuthorizationUtilTest {
     assertThat(status.getDescription()).endsWith("not authorized");
   }
 
+  @Test
+  public void altsAuthorizationCheck_ignoresCase() throws Exception {
+    Status status =
+        AuthorizationUtil.clientAuthorizationCheck(
+            new FakeServerCall("alice"), Lists.newArrayList("ALICE", "Bob"));
+    assertThat(status.getCode()).isEqualTo(Status.Code.OK);
+  }
+
   private static class FakeServerCall extends ServerCall<String, String> {
     final Attributes attrs;
 

./gradlew :grpc-alts:test --tests io.grpc.alts.AuthorizationUtilTest -PskipCodegen=true -PskipAndroid=true

AuthorizationUtilTest > altsAuthorizationCheck_ignoresCase FAILED
    value of: getCode()
    expected: OK
    but was : PERMISSION_DENIED
        at app//io.grpc.alts.AuthorizationUtilTest.altsAuthorizationCheck_ignoresCase(AuthorizationUtilTest.java:63)

152 tests completed, 1 failed

Environment:

Already fixed in grpc/grpc-go

PR: https://github.com/grpc/grpc-go/pull/3792 ("credentials/alts: ClientAuthorizationCheck to case-fold compare of peer SA", merged 2020-09-01T23:23:56Z, merge commit 48bf772d0c2). It switched the peer service account comparison to strings.EqualFold.

How grpc-go fixed it (relevant hunks, verbatim):

--- a/credentials/alts/utils.go
+++ b/credentials/alts/utils.go
@@ -152,12 +152,13 @@ func AuthInfoFromPeer(p *peer.Peer) (AuthInfo, error) {
 func ClientAuthorizationCheck(ctx context.Context, expectedServiceAccounts []string) error {
 	authInfo, err := AuthInfoFromContext(ctx)
 	if err != nil {
-		return status.Newf(codes.PermissionDenied, "The context is not an ALTS-compatible context: %v", err).Err()
+		return status.Errorf(codes.PermissionDenied, "The context is not an ALTS-compatible context: %v", err)
 	}
+	peer := authInfo.PeerServiceAccount()
 	for _, sa := range expectedServiceAccounts {
-		if authInfo.PeerServiceAccount() == sa {
+		if strings.EqualFold(peer, sa) {
 			return nil
 		}
 	}
-	return status.Newf(codes.PermissionDenied, "Client %v is not authorized", authInfo.PeerServiceAccount()).Err()
+	return status.Errorf(codes.PermissionDenied, "Client %v is not authorized", peer)
 }

Suggested fix

Compare the peer service account to each expected entry with equalsIgnoreCase, and document it:

diff --git a/alts/src/main/java/io/grpc/alts/AuthorizationUtil.java b/alts/src/main/java/io/grpc/alts/AuthorizationUtil.java
--- a/alts/src/main/java/io/grpc/alts/AuthorizationUtil.java
+++ b/alts/src/main/java/io/grpc/alts/AuthorizationUtil.java
@@ -29,8 +29,8 @@ public final class AuthorizationUtil {
 
   /**
    * Given a server call, performs client authorization check, i.e., checks if the client service
-   * account matches one of the expected service accounts. It returns OK if client is authorized and
-   * an error otherwise.
+   * account matches one of the expected service accounts, ignoring case. It returns OK if client
+   * is authorized and an error otherwise.
    */
   public static Status clientAuthorizationCheck(
       ServerCall<?, ?> call, Collection<String> expectedServiceAccounts) {
@@ -39,10 +39,13 @@ public final class AuthorizationUtil {
     if (altsContext == null) {
       return Status.PERMISSION_DENIED.withDescription("Peer ALTS AuthContext not found");
     }
-    if (expectedServiceAccounts.contains(altsContext.getPeerServiceAccount())) {
-      return Status.OK;
+    String peerServiceAccount = altsContext.getPeerServiceAccount();
+    for (String serviceAccount : expectedServiceAccounts) {
+      if (peerServiceAccount.equalsIgnoreCase(serviceAccount)) {
+        return Status.OK;
+      }
     }
     return Status.PERMISSION_DENIED.withDescription(
-        "Client " + altsContext.getPeerServiceAccount() + " is not authorized");
+        "Client " + peerServiceAccount + " is not authorized");
   }
 }

Verified on 15d64a4 (OpenJDK 21.0.2, Gradle 8.14.5): the test above fails without this patch and passes with it; no other test results change (:grpc-alts:test).

I can submit a PR for this.

Checked: searches for clientAuthorizationCheck case, ALTS service account case-insensitive and AuthorizationUtil found only #11042 and #7840 (ALTS context API changes), not this comparison.

Lingua principale
Java
Stelle
12.1k
Fork
4k
Merge medio
1g 13h
PR unite (30g)
42

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di grpc/grpc-java

Tutte le issue di grpc/grpc-java

Issue simili

Altre issue su Java

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.