urlcredsource.go 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. // Copyright 2020 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package externalaccount
  5. import (
  6. "context"
  7. "encoding/json"
  8. "errors"
  9. "fmt"
  10. "io"
  11. "io/ioutil"
  12. "net/http"
  13. "golang.org/x/oauth2"
  14. )
  15. type urlCredentialSource struct {
  16. URL string
  17. Headers map[string]string
  18. Format format
  19. ctx context.Context
  20. }
  21. func (cs urlCredentialSource) credentialSourceType() string {
  22. return "url"
  23. }
  24. func (cs urlCredentialSource) subjectToken() (string, error) {
  25. client := oauth2.NewClient(cs.ctx, nil)
  26. req, err := http.NewRequest("GET", cs.URL, nil)
  27. if err != nil {
  28. return "", fmt.Errorf("oauth2/google: HTTP request for URL-sourced credential failed: %v", err)
  29. }
  30. req = req.WithContext(cs.ctx)
  31. for key, val := range cs.Headers {
  32. req.Header.Add(key, val)
  33. }
  34. resp, err := client.Do(req)
  35. if err != nil {
  36. return "", fmt.Errorf("oauth2/google: invalid response when retrieving subject token: %v", err)
  37. }
  38. defer resp.Body.Close()
  39. respBody, err := ioutil.ReadAll(io.LimitReader(resp.Body, 1<<20))
  40. if err != nil {
  41. return "", fmt.Errorf("oauth2/google: invalid body in subject token URL query: %v", err)
  42. }
  43. if c := resp.StatusCode; c < 200 || c > 299 {
  44. return "", fmt.Errorf("oauth2/google: status code %d: %s", c, respBody)
  45. }
  46. switch cs.Format.Type {
  47. case "json":
  48. jsonData := make(map[string]interface{})
  49. err = json.Unmarshal(respBody, &jsonData)
  50. if err != nil {
  51. return "", fmt.Errorf("oauth2/google: failed to unmarshal subject token file: %v", err)
  52. }
  53. val, ok := jsonData[cs.Format.SubjectTokenFieldName]
  54. if !ok {
  55. return "", errors.New("oauth2/google: provided subject_token_field_name not found in credentials")
  56. }
  57. token, ok := val.(string)
  58. if !ok {
  59. return "", errors.New("oauth2/google: improperly formatted subject token")
  60. }
  61. return token, nil
  62. case "text":
  63. return string(respBody), nil
  64. case "":
  65. return string(respBody), nil
  66. default:
  67. return "", errors.New("oauth2/google: invalid credential_source file format type")
  68. }
  69. }