You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

sts_client_grants.go 5.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /*
  2. * MinIO Go Library for Amazon S3 Compatible Cloud Storage
  3. * Copyright 2019 MinIO, Inc.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package credentials
  18. import (
  19. "encoding/xml"
  20. "errors"
  21. "fmt"
  22. "net/http"
  23. "net/url"
  24. "time"
  25. )
  26. // AssumedRoleUser - The identifiers for the temporary security credentials that
  27. // the operation returns. Please also see https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumedRoleUser
  28. type AssumedRoleUser struct {
  29. Arn string
  30. AssumedRoleID string `xml:"AssumeRoleId"`
  31. }
  32. // AssumeRoleWithClientGrantsResponse contains the result of successful AssumeRoleWithClientGrants request.
  33. type AssumeRoleWithClientGrantsResponse struct {
  34. XMLName xml.Name `xml:"https://sts.amazonaws.com/doc/2011-06-15/ AssumeRoleWithClientGrantsResponse" json:"-"`
  35. Result ClientGrantsResult `xml:"AssumeRoleWithClientGrantsResult"`
  36. ResponseMetadata struct {
  37. RequestID string `xml:"RequestId,omitempty"`
  38. } `xml:"ResponseMetadata,omitempty"`
  39. }
  40. // ClientGrantsResult - Contains the response to a successful AssumeRoleWithClientGrants
  41. // request, including temporary credentials that can be used to make MinIO API requests.
  42. type ClientGrantsResult struct {
  43. AssumedRoleUser AssumedRoleUser `xml:",omitempty"`
  44. Audience string `xml:",omitempty"`
  45. Credentials struct {
  46. AccessKey string `xml:"AccessKeyId" json:"accessKey,omitempty"`
  47. SecretKey string `xml:"SecretAccessKey" json:"secretKey,omitempty"`
  48. Expiration time.Time `xml:"Expiration" json:"expiration,omitempty"`
  49. SessionToken string `xml:"SessionToken" json:"sessionToken,omitempty"`
  50. } `xml:",omitempty"`
  51. PackedPolicySize int `xml:",omitempty"`
  52. Provider string `xml:",omitempty"`
  53. SubjectFromClientGrantsToken string `xml:",omitempty"`
  54. }
  55. // ClientGrantsToken - client grants token with expiry.
  56. type ClientGrantsToken struct {
  57. Token string
  58. Expiry int
  59. }
  60. // A STSClientGrants retrieves credentials from MinIO service, and keeps track if
  61. // those credentials are expired.
  62. type STSClientGrants struct {
  63. Expiry
  64. // Required http Client to use when connecting to MinIO STS service.
  65. Client *http.Client
  66. // MinIO endpoint to fetch STS credentials.
  67. STSEndpoint string
  68. // getClientGrantsTokenExpiry function to retrieve tokens
  69. // from IDP This function should return two values one is
  70. // accessToken which is a self contained access token (JWT)
  71. // and second return value is the expiry associated with
  72. // this token. This is a customer provided function and
  73. // is mandatory.
  74. GetClientGrantsTokenExpiry func() (*ClientGrantsToken, error)
  75. }
  76. // NewSTSClientGrants returns a pointer to a new
  77. // Credentials object wrapping the STSClientGrants.
  78. func NewSTSClientGrants(stsEndpoint string, getClientGrantsTokenExpiry func() (*ClientGrantsToken, error)) (*Credentials, error) {
  79. if stsEndpoint == "" {
  80. return nil, errors.New("STS endpoint cannot be empty")
  81. }
  82. if getClientGrantsTokenExpiry == nil {
  83. return nil, errors.New("Client grants access token and expiry retrieval function should be defined")
  84. }
  85. return New(&STSClientGrants{
  86. Client: &http.Client{
  87. Transport: http.DefaultTransport,
  88. },
  89. STSEndpoint: stsEndpoint,
  90. GetClientGrantsTokenExpiry: getClientGrantsTokenExpiry,
  91. }), nil
  92. }
  93. func getClientGrantsCredentials(clnt *http.Client, endpoint string,
  94. getClientGrantsTokenExpiry func() (*ClientGrantsToken, error)) (AssumeRoleWithClientGrantsResponse, error) {
  95. accessToken, err := getClientGrantsTokenExpiry()
  96. if err != nil {
  97. return AssumeRoleWithClientGrantsResponse{}, err
  98. }
  99. v := url.Values{}
  100. v.Set("Action", "AssumeRoleWithClientGrants")
  101. v.Set("Token", accessToken.Token)
  102. v.Set("DurationSeconds", fmt.Sprintf("%d", accessToken.Expiry))
  103. v.Set("Version", STSVersion)
  104. u, err := url.Parse(endpoint)
  105. if err != nil {
  106. return AssumeRoleWithClientGrantsResponse{}, err
  107. }
  108. u.RawQuery = v.Encode()
  109. req, err := http.NewRequest(http.MethodPost, u.String(), nil)
  110. if err != nil {
  111. return AssumeRoleWithClientGrantsResponse{}, err
  112. }
  113. resp, err := clnt.Do(req)
  114. if err != nil {
  115. return AssumeRoleWithClientGrantsResponse{}, err
  116. }
  117. defer resp.Body.Close()
  118. if resp.StatusCode != http.StatusOK {
  119. return AssumeRoleWithClientGrantsResponse{}, errors.New(resp.Status)
  120. }
  121. a := AssumeRoleWithClientGrantsResponse{}
  122. if err = xml.NewDecoder(resp.Body).Decode(&a); err != nil {
  123. return AssumeRoleWithClientGrantsResponse{}, err
  124. }
  125. return a, nil
  126. }
  127. // Retrieve retrieves credentials from the MinIO service.
  128. // Error will be returned if the request fails.
  129. func (m *STSClientGrants) Retrieve() (Value, error) {
  130. a, err := getClientGrantsCredentials(m.Client, m.STSEndpoint, m.GetClientGrantsTokenExpiry)
  131. if err != nil {
  132. return Value{}, err
  133. }
  134. // Expiry window is set to 10secs.
  135. m.SetExpiration(a.Result.Credentials.Expiration, DefaultExpiryWindow)
  136. return Value{
  137. AccessKeyID: a.Result.Credentials.AccessKey,
  138. SecretAccessKey: a.Result.Credentials.SecretKey,
  139. SessionToken: a.Result.Credentials.SessionToken,
  140. SignerType: SignatureV4,
  141. }, nil
  142. }