...

Source file src/cloud.google.com/go/auth/credentials/selfsignedjwt_test.go

Documentation: cloud.google.com/go/auth/credentials

     1  // Copyright 2023 Google LLC
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package credentials
    16  
    17  import (
    18  	"bytes"
    19  	"context"
    20  	"crypto/rand"
    21  	"crypto/rsa"
    22  	"crypto/x509"
    23  	"encoding/base64"
    24  	"encoding/json"
    25  	"encoding/pem"
    26  	"strings"
    27  	"testing"
    28  	"time"
    29  
    30  	"cloud.google.com/go/auth/internal/jwt"
    31  )
    32  
    33  var jwtJSONKey = []byte(`{
    34  	"private_key_id": "268f54e43a1af97cfc71731688434f45aca15c8b",
    35  	"private_key": "super secret key",
    36  	"client_email": "gopher@developer.gserviceaccount.com",
    37  	"client_id": "gopher.apps.googleusercontent.com",
    38  	"token_uri": "https://accountp.google.com/o/gophers/token",
    39  	"type": "service_account",
    40  	"audience": "https://testpervice.googleapis.com/"
    41    }`)
    42  
    43  func TestDefaultCredentials_SelfSignedJSON(t *testing.T) {
    44  	privateKey, jsonKey, err := setupFakeKey()
    45  	if err != nil {
    46  		t.Fatal(err)
    47  	}
    48  	tp, err := DetectDefault(&DetectOptions{
    49  		CredentialsJSON:  jsonKey,
    50  		Audience:         "audience",
    51  		UseSelfSignedJWT: true,
    52  	})
    53  	if err != nil {
    54  		t.Fatalf("DefaultCredentials(%s): %v", jsonKey, err)
    55  	}
    56  
    57  	tok, err := tp.Token(context.Background())
    58  	if err != nil {
    59  		t.Fatalf("Token(): %v", err)
    60  	}
    61  
    62  	if got, want := tok.Type, "Bearer"; got != want {
    63  		t.Errorf("Type = %q, want %q", got, want)
    64  	}
    65  	if got := tok.Expiry; tok.Expiry.Before(time.Now()) {
    66  		t.Errorf("Expiry = %v, should not be expired", got)
    67  	}
    68  
    69  	err = jwt.VerifyJWS(tok.Value, &privateKey.PublicKey)
    70  	if err != nil {
    71  		t.Errorf("jwt.Verify(%q): %v", tok.Value, err)
    72  	}
    73  
    74  	claim, err := jwt.DecodeJWS(tok.Value)
    75  	if err != nil {
    76  		t.Fatalf("jwt.Decode(%q): %v", tok.Value, err)
    77  	}
    78  
    79  	if got, want := claim.Iss, "gopher@developer.gserviceaccount.com"; got != want {
    80  		t.Errorf("Iss = %q, want %q", got, want)
    81  	}
    82  	if got, want := claim.Sub, "gopher@developer.gserviceaccount.com"; got != want {
    83  		t.Errorf("Sub = %q, want %q", got, want)
    84  	}
    85  	if got, want := claim.Aud, "audience"; got != want {
    86  		t.Errorf("Aud = %q, want %q", got, want)
    87  	}
    88  
    89  	// Finally, check the header private key.
    90  	tokParts := strings.Split(tok.Value, ".")
    91  	hdrJSON, err := base64.RawURLEncoding.DecodeString(tokParts[0])
    92  	if err != nil {
    93  		t.Fatalf("DecodeString(%q): %v", tokParts[0], err)
    94  	}
    95  	var hdr jwt.Header
    96  	if err := json.Unmarshal(hdrJSON, &hdr); err != nil {
    97  		t.Fatalf("json.Unmarshal(%q): %v", hdrJSON, err)
    98  	}
    99  
   100  	if got, want := hdr.KeyID, "268f54e43a1af97cfc71731688434f45aca15c8b"; got != want {
   101  		t.Errorf("KeyID = %q, want %q", got, want)
   102  	}
   103  }
   104  
   105  func TestDefaultCredentials_SelfSignedWithScope(t *testing.T) {
   106  	privateKey, jsonKey, err := setupFakeKey()
   107  	if err != nil {
   108  		t.Fatal(err)
   109  	}
   110  	tp, err := DetectDefault(&DetectOptions{
   111  		CredentialsJSON:  jsonKey,
   112  		Scopes:           []string{"scope1", "scope2"},
   113  		UseSelfSignedJWT: true,
   114  	})
   115  	if err != nil {
   116  		t.Fatalf("DefaultCredentials(%s): %v", jsonKey, err)
   117  	}
   118  
   119  	tok, err := tp.Token(context.Background())
   120  	if err != nil {
   121  		t.Fatalf("Token(): %v", err)
   122  	}
   123  
   124  	if got, want := tok.Type, "Bearer"; got != want {
   125  		t.Errorf("TokenType = %q, want %q", got, want)
   126  	}
   127  	if got := tok.Expiry; tok.Expiry.Before(time.Now()) {
   128  		t.Errorf("Expiry = %v, should not be expired", got)
   129  	}
   130  
   131  	err = jwt.VerifyJWS(tok.Value, &privateKey.PublicKey)
   132  	if err != nil {
   133  		t.Errorf("jwt.Verify(%q): %v", tok.Value, err)
   134  	}
   135  
   136  	claim, err := jwt.DecodeJWS(tok.Value)
   137  	if err != nil {
   138  		t.Fatalf("jwt.Decode(%q): %v", tok.Value, err)
   139  	}
   140  
   141  	if got, want := claim.Iss, "gopher@developer.gserviceaccount.com"; got != want {
   142  		t.Errorf("Iss = %q, want %q", got, want)
   143  	}
   144  	if got, want := claim.Sub, "gopher@developer.gserviceaccount.com"; got != want {
   145  		t.Errorf("Sub = %q, want %q", got, want)
   146  	}
   147  	if got, want := claim.Scope, "scope1 scope2"; got != want {
   148  		t.Errorf("Aud = %q, want %q", got, want)
   149  	}
   150  
   151  	// Finally, check the header private key.
   152  	tokParts := strings.Split(tok.Value, ".")
   153  	hdrJSON, err := base64.RawURLEncoding.DecodeString(tokParts[0])
   154  	if err != nil {
   155  		t.Fatalf("DecodeString(%q): %v", tokParts[0], err)
   156  	}
   157  	var hdr jwt.Header
   158  	if err := json.Unmarshal(hdrJSON, &hdr); err != nil {
   159  		t.Fatalf("json.Unmarshal(%q): %v", hdrJSON, err)
   160  	}
   161  
   162  	if got, want := hdr.KeyID, "268f54e43a1af97cfc71731688434f45aca15c8b"; got != want {
   163  		t.Errorf("KeyID = %q, want %q", got, want)
   164  	}
   165  }
   166  
   167  // setupFakeKey generates a key we can use in the test data.
   168  func setupFakeKey() (*rsa.PrivateKey, []byte, error) {
   169  	// Generate a key we can use in the test data.
   170  	pk, err := rsa.GenerateKey(rand.Reader, 2048)
   171  	if err != nil {
   172  		return nil, nil, err
   173  	}
   174  	// Encode the key and substitute into our example JSON.
   175  	enc := pem.EncodeToMemory(&pem.Block{
   176  		Type:  "PRIVATE KEY",
   177  		Bytes: x509.MarshalPKCS1PrivateKey(pk),
   178  	})
   179  	enc, err = json.Marshal(string(enc))
   180  	if err != nil {
   181  		return nil, nil, err
   182  	}
   183  	return pk, bytes.Replace(jwtJSONKey, []byte(`"super secret key"`), enc, 1), nil
   184  }
   185  

View as plain text