cloudtrail.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. // Copyright 2019 Yunion
  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 aws
  15. import (
  16. "fmt"
  17. "strings"
  18. "time"
  19. "github.com/aws/aws-sdk-go/aws/session"
  20. "github.com/aws/aws-sdk-go/service/cloudtrail"
  21. "yunion.io/x/jsonutils"
  22. "yunion.io/x/log"
  23. "yunion.io/x/pkg/errors"
  24. "yunion.io/x/cloudmux/pkg/cloudprovider"
  25. )
  26. type SEventResource struct {
  27. // The name of the resource referenced by the event returned. These are user-created
  28. // names whose values will depend on the environment. For example, the resource
  29. // name might be "auto-scaling-test-group" for an Auto Scaling Group or "i-1234567"
  30. // for an EC2 Instance.
  31. ResourceName string `type:"string"`
  32. // The type of a resource referenced by the event returned. When the resource
  33. // type cannot be determined, null is returned. Some examples of resource types
  34. // are: Instance for EC2, Trail for CloudTrail, DBInstance for RDS, and AccessKey
  35. // for IAM. To learn more about how to look up and filter events by the resource
  36. // types supported for a service, see Filtering CloudTrail Events (https://docs.aws.amazon.com/awscloudtrail/latest/userguide/view-cloudtrail-events-console.html#filtering-cloudtrail-events).
  37. ResourceType string `type:"string"`
  38. }
  39. type SEvent struct {
  40. // The AWS access key ID that was used to sign the request. If the request was
  41. // made with temporary security credentials, this is the access key ID of the
  42. // temporary credentials.
  43. AccessKeyId string `type:"string"`
  44. // A JSON string that contains a representation of the event returned.
  45. CloudTrailEvent string `type:"string"`
  46. // The CloudTrail ID of the event returned.
  47. EventId string `type:"string"`
  48. // The name of the event returned.
  49. EventName string `type:"string"`
  50. // The AWS service that the request was made to.
  51. EventSource string `type:"string"`
  52. // The date and time of the event returned.
  53. EventTime time.Time `type:"timestamp"`
  54. // Information about whether the event is a write event or a read event.
  55. ReadOnly string `type:"string"`
  56. // A list of resources referenced by the event returned.
  57. Resources []SEventResource `type:"list"`
  58. // A user name or role name of the requester that called the API in the event
  59. // returned.
  60. Username string `type:"string"`
  61. }
  62. func (self *SEvent) GetName() string {
  63. return self.EventName
  64. }
  65. func (self *SEvent) GetService() string {
  66. return self.EventSource
  67. }
  68. func (self *SEvent) GetAction() string {
  69. return self.EventName
  70. }
  71. func (self *SEvent) GetResourceType() string {
  72. return self.EventSource
  73. }
  74. func (self *SEvent) GetRequestId() string {
  75. return self.EventId
  76. }
  77. func (self *SEvent) GetRequest() jsonutils.JSONObject {
  78. obj, _ := jsonutils.Parse([]byte(self.CloudTrailEvent))
  79. return obj
  80. }
  81. func (self *SEvent) GetAccount() string {
  82. return fmt.Sprintf("%s(%s)", self.AccessKeyId, self.Username)
  83. }
  84. func (self *SEvent) IsSuccess() bool {
  85. return !strings.Contains(self.CloudTrailEvent, "errorMessage")
  86. }
  87. func (self *SEvent) GetCreatedAt() time.Time {
  88. return self.EventTime
  89. }
  90. func (self *SRegion) getAwsCloudtrailSession() (*session.Session, error) {
  91. session, err := self.getAwsSession()
  92. if err != nil {
  93. return nil, errors.Wrap(err, "client.getDefaultSession()")
  94. }
  95. session.ClientConfig(CLOUD_TRAIL_SERVICE_NAME)
  96. return session, nil
  97. }
  98. func (self *SRegion) LookupEvents(start, end time.Time, withReadEvent bool) ([]SEvent, error) {
  99. s, err := self.getAwsCloudtrailSession()
  100. if err != nil {
  101. return nil, errors.Wrapf(err, "getAwsCloudtrailSession")
  102. }
  103. client := cloudtrail.New(s)
  104. input := &cloudtrail.LookupEventsInput{LookupAttributes: []*cloudtrail.LookupAttribute{}}
  105. if !start.IsZero() {
  106. input.SetStartTime(start)
  107. }
  108. if !end.IsZero() {
  109. input.SetEndTime(end)
  110. }
  111. if !withReadEvent {
  112. readonly := "ReadOnly"
  113. val := "false"
  114. input.LookupAttributes = append(input.LookupAttributes, &cloudtrail.LookupAttribute{
  115. AttributeKey: &readonly,
  116. AttributeValue: &val,
  117. })
  118. }
  119. events := []SEvent{}
  120. nextToken := ""
  121. for {
  122. if len(nextToken) > 0 {
  123. input.SetNextToken(nextToken)
  124. }
  125. var output *cloudtrail.LookupEventsOutput = nil
  126. for {
  127. output, err = client.LookupEvents(input)
  128. if err != nil {
  129. if strings.Contains(err.Error(), "ThrottlingException") {
  130. log.Warningf("LookupEvents ThrottlingException, try after 3 seconds")
  131. time.Sleep(time.Second * 3)
  132. continue
  133. }
  134. return nil, errors.Wrapf(err, "LookupEvents(%s, %s)", start, end)
  135. }
  136. break
  137. }
  138. for i := range output.Events {
  139. err := FillZero(output.Events[i])
  140. if err != nil {
  141. return nil, errors.Wrapf(err, "FillZero")
  142. }
  143. event := SEvent{}
  144. err = jsonutils.Update(&event, jsonutils.Marshal(output.Events[i]))
  145. if err != nil {
  146. return nil, errors.Wrapf(err, "jsonutils.Update")
  147. }
  148. if strings.Contains(event.CloudTrailEvent, "awsRegion") && !strings.Contains(event.CloudTrailEvent, fmt.Sprintf(`"awsRegion":"%s"`, self.RegionId)) {
  149. continue
  150. }
  151. events = append(events, event)
  152. }
  153. nextToken = ""
  154. if output.NextToken != nil {
  155. nextToken = *output.NextToken
  156. }
  157. if len(nextToken) == 0 {
  158. break
  159. }
  160. }
  161. return events, nil
  162. }
  163. func (self *SRegion) GetICloudEvents(start time.Time, end time.Time, withReadEvent bool) ([]cloudprovider.ICloudEvent, error) {
  164. events, err := self.LookupEvents(start, end, withReadEvent)
  165. if err != nil {
  166. return nil, errors.Wrapf(err, "LookupEvents(%s, %s)", start, end)
  167. }
  168. ret := []cloudprovider.ICloudEvent{}
  169. for i := range events {
  170. ret = append(ret, &events[i])
  171. }
  172. return ret, nil
  173. }