Skip to content

Commit

Permalink
Add support for the AuditTrail API
Browse files Browse the repository at this point in the history
  • Loading branch information
sebasslash committed May 23, 2022
1 parent 1241af2 commit b423b2d
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 0 deletions.
131 changes: 131 additions & 0 deletions audit_trail.go
@@ -0,0 +1,131 @@
package tfe

import (
"context"
"encoding/json"
"io/ioutil"
"net/http"
"time"

"github.com/google/go-querystring/query"
retryablehttp "github.com/hashicorp/go-retryablehttp"
)

// Compile-time proof of interface implementation
var _ AuditTrails = (*auditTrails)(nil)

// AuditTrails describes all the audit event related methods that the Terraform
// Cloud API supports. **Note:** These methods require an organization token for
// an organization in the Business tier.
//
// TFC API Docs: https://www.terraform.io/cloud-docs/api-docs/audit-trails
type AuditTrails interface {
// Read all the audit events in an organization.
Read(ctx context.Context, orgToken string, options *AuditTrailReadOptions) (*AuditTrailList, error)
}

// auditTrails implements AuditTrails
type auditTrails struct {
client *Client
}

// AuditTrailRequest represents the request details of the audit event.
type AuditTrailRequest struct {
ID string `json:"id"`
}

// AuditTrailAuth represents the details of the actor that invoked the audit event.
type AuditTrailAuth struct {
AccessorID string `json:"accessor_id"`
Description string `json:"description"`
Type string `json:"type"`
ImpersonatorID *string `json:"impersonator_id"`
OrganizationID string `json:"organization_id"`
}

// AuditTrailResource represents the details of the API resource in the audit event.
type AuditTrailResource struct {
ID string `json:"id"`
Type string `json:"type"`
Action string `json:"create"`
Meta *map[string]interface{} `json:"meta"`
}

// AuditTrail represents an event in the TFC audit log.
type AuditTrail struct {
ID string `json:"id"`
Version string `json:"version"`
Type string `json:"type"`
Timestamp time.Time `json:"timestamp"`

Auth *AuditTrailAuth `json:"auth"`
Request *AuditTrailRequest `json:"request"`
Resource *AuditTrailResource `json:"resource"`
}

// AuditTrailList represents a list of audit trails.
type AuditTrailList struct {
*Pagination

Items []*AuditTrail `json:"data"`
}

// AuditTrailReadOptions represents the options for reading audit trails.
type AuditTrailReadOptions struct {
// Optional: Returns only audit trails created after this date
Since time.Time `url:"since,omitempty"`
*ListOptions
}

// Read all the audit events in an organization.
func (s *auditTrails) Read(ctx context.Context, orgToken string, options *AuditTrailReadOptions) (*AuditTrailList, error) {
u, err := s.client.baseURL.Parse("/api/v2/organization/audit-trail")
if err != nil {
return nil, err
}

headers := make(http.Header)
headers.Set("Authorization", "Bearer "+orgToken)
headers.Set("Content-Type", "application/json")

if options != nil {
q, err := query.Values(options)
if err != nil {
return nil, err
}

u.RawQuery = encodeQueryParams(q)
}

req, err := retryablehttp.NewRequest("GET", u.String(), nil)
if err != nil {
return nil, err
}

if err := s.client.limiter.Wait(ctx); err != nil {
return nil, err
}

resp, err := s.client.http.Do(req.WithContext(ctx))
if err != nil {
select {
case <-ctx.Done():
return nil, ctx.Err()
default:
return nil, err
}
}
defer resp.Body.Close()

body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}

atl := &AuditTrailList{}
if err := json.Unmarshal(body, atl); err != nil {
return nil, err
}

return atl, nil
}
2 changes: 2 additions & 0 deletions tfe.go
Expand Up @@ -110,6 +110,7 @@ type Client struct {
AgentPools AgentPools
AgentTokens AgentTokens
Applies Applies
AuditTrails AuditTrails
Comments Comments
ConfigurationVersions ConfigurationVersions
CostEstimates CostEstimates
Expand Down Expand Up @@ -254,6 +255,7 @@ func NewClient(cfg *Config) (*Client, error) {
client.AgentPools = &agentPools{client: client}
client.AgentTokens = &agentTokens{client: client}
client.Applies = &applies{client: client}
client.AuditTrails = &auditTrails{client: client}
client.Comments = &comments{client: client}
client.ConfigurationVersions = &configurationVersions{client: client}
client.CostEstimates = &costEstimates{client: client}
Expand Down

0 comments on commit b423b2d

Please sign in to comment.