selfsignedjwt.go 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  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. package credentials
  15. import (
  16. "context"
  17. "crypto/rsa"
  18. "errors"
  19. "fmt"
  20. "strings"
  21. "time"
  22. "cloud.google.com/go/auth"
  23. "cloud.google.com/go/auth/internal"
  24. "cloud.google.com/go/auth/internal/credsfile"
  25. "cloud.google.com/go/auth/internal/jwt"
  26. )
  27. var (
  28. // for testing
  29. now func() time.Time = time.Now
  30. )
  31. // configureSelfSignedJWT uses the private key in the service account to create
  32. // a JWT without making a network call.
  33. func configureSelfSignedJWT(f *credsfile.ServiceAccountFile, opts *DetectOptions) (auth.TokenProvider, error) {
  34. if len(opts.scopes()) == 0 && opts.Audience == "" {
  35. return nil, errors.New("credentials: both scopes and audience are empty")
  36. }
  37. pk, err := internal.ParseKey([]byte(f.PrivateKey))
  38. if err != nil {
  39. return nil, fmt.Errorf("credentials: could not parse key: %w", err)
  40. }
  41. return &selfSignedTokenProvider{
  42. email: f.ClientEmail,
  43. audience: opts.Audience,
  44. scopes: opts.scopes(),
  45. pk: pk,
  46. pkID: f.PrivateKeyID,
  47. }, nil
  48. }
  49. type selfSignedTokenProvider struct {
  50. email string
  51. audience string
  52. scopes []string
  53. pk *rsa.PrivateKey
  54. pkID string
  55. }
  56. func (tp *selfSignedTokenProvider) Token(context.Context) (*auth.Token, error) {
  57. iat := now()
  58. exp := iat.Add(time.Hour)
  59. scope := strings.Join(tp.scopes, " ")
  60. c := &jwt.Claims{
  61. Iss: tp.email,
  62. Sub: tp.email,
  63. Aud: tp.audience,
  64. Scope: scope,
  65. Iat: iat.Unix(),
  66. Exp: exp.Unix(),
  67. }
  68. h := &jwt.Header{
  69. Algorithm: jwt.HeaderAlgRSA256,
  70. Type: jwt.HeaderType,
  71. KeyID: string(tp.pkID),
  72. }
  73. msg, err := jwt.EncodeJWS(h, c, tp.pk)
  74. if err != nil {
  75. return nil, fmt.Errorf("credentials: could not encode JWT: %w", err)
  76. }
  77. return &auth.Token{Value: msg, Type: internal.TokenTypeBearer, Expiry: exp}, nil
  78. }