diff --git a/builtin/providers/aws/config.go b/builtin/providers/aws/config.go index b8fc9fa476..298d24ccde 100644 --- a/builtin/providers/aws/config.go +++ b/builtin/providers/aws/config.go @@ -13,6 +13,7 @@ import ( "github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go/service/autoscaling" "github.com/aws/aws-sdk-go/service/cloudformation" + "github.com/aws/aws-sdk-go/service/cloudtrail" "github.com/aws/aws-sdk-go/service/cloudwatch" "github.com/aws/aws-sdk-go/service/cloudwatchlogs" "github.com/aws/aws-sdk-go/service/codedeploy" @@ -51,6 +52,7 @@ type Config struct { type AWSClient struct { cfconn *cloudformation.CloudFormation + cloudtrailconn *cloudtrail.CloudTrail cloudwatchconn *cloudwatch.CloudWatch cloudwatchlogsconn *cloudwatchlogs.CloudWatchLogs dsconn *directoryservice.DirectoryService @@ -188,6 +190,9 @@ func (c *Config) Client() (interface{}, error) { log.Println("[INFO] Initializing CloudWatch SDK connection") client.cloudwatchconn = cloudwatch.New(awsConfig) + log.Println("[INFO] Initializing CloudTrail connection") + client.cloudtrailconn = cloudtrail.New(awsConfig) + log.Println("[INFO] Initializing CloudWatch Logs connection") client.cloudwatchlogsconn = cloudwatchlogs.New(awsConfig) diff --git a/builtin/providers/aws/provider.go b/builtin/providers/aws/provider.go index 5b02d4a70a..d4567e2385 100644 --- a/builtin/providers/aws/provider.go +++ b/builtin/providers/aws/provider.go @@ -164,6 +164,7 @@ func Provider() terraform.ResourceProvider { "aws_autoscaling_notification": resourceAwsAutoscalingNotification(), "aws_autoscaling_policy": resourceAwsAutoscalingPolicy(), "aws_cloudformation_stack": resourceAwsCloudFormationStack(), + "aws_cloudtrail": resourceAwsCloudTrail(), "aws_cloudwatch_log_group": resourceAwsCloudWatchLogGroup(), "aws_autoscaling_lifecycle_hook": resourceAwsAutoscalingLifecycleHook(), "aws_cloudwatch_metric_alarm": resourceAwsCloudWatchMetricAlarm(), diff --git a/builtin/providers/aws/resource_aws_cloudtrail.go b/builtin/providers/aws/resource_aws_cloudtrail.go new file mode 100644 index 0000000000..eed420edf4 --- /dev/null +++ b/builtin/providers/aws/resource_aws_cloudtrail.go @@ -0,0 +1,167 @@ +package aws + +import ( + "fmt" + "log" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/cloudtrail" + "github.com/hashicorp/terraform/helper/schema" +) + +func resourceAwsCloudTrail() *schema.Resource { + return &schema.Resource{ + Create: resourceAwsCloudTrailCreate, + Read: resourceAwsCloudTrailRead, + Update: resourceAwsCloudTrailUpdate, + Delete: resourceAwsCloudTrailDelete, + + Schema: map[string]*schema.Schema{ + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "s3_bucket_name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + "s3_key_prefix": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + }, + "cloud_watch_logs_role_arn": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + }, + "cloud_watch_logs_group_arn": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + }, + "include_global_service_events": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + "sns_topic_name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + }, + }, + } +} + +func resourceAwsCloudTrailCreate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).cloudtrailconn + + input := cloudtrail.CreateTrailInput{ + Name: aws.String(d.Get("name").(string)), + S3BucketName: aws.String(d.Get("s3_bucket_name").(string)), + } + + if v, ok := d.GetOk("cloud_watch_logs_group_arn"); ok { + input.CloudWatchLogsLogGroupArn = aws.String(v.(string)) + } + if v, ok := d.GetOk("cloud_watch_logs_role_arn"); ok { + input.CloudWatchLogsRoleArn = aws.String(v.(string)) + } + if v, ok := d.GetOk("include_global_service_events"); ok { + input.IncludeGlobalServiceEvents = aws.Bool(v.(bool)) + } + if v, ok := d.GetOk("s3_key_prefix"); ok { + input.S3KeyPrefix = aws.String(v.(string)) + } + if v, ok := d.GetOk("sns_topic_name"); ok { + input.SnsTopicName = aws.String(v.(string)) + } + + t, err := conn.CreateTrail(&input) + if err != nil { + return err + } + + log.Printf("[DEBUG] CloudTrail created: %s", t) + + d.SetId(*t.Name) + + return resourceAwsCloudTrailRead(d, meta) +} + +func resourceAwsCloudTrailRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).cloudtrailconn + + name := d.Get("name").(string) + input := cloudtrail.DescribeTrailsInput{ + TrailNameList: []*string{ + aws.String(name), + }, + } + resp, err := conn.DescribeTrails(&input) + if err != nil { + return err + } + if len(resp.TrailList) == 0 { + return fmt.Errorf("No CloudTrail found, using name %q", name) + } + + trail := resp.TrailList[0] + log.Printf("[DEBUG] CloudTrail received: %s", trail) + + d.Set("name", trail.Name) + d.Set("s3_bucket_name", trail.S3BucketName) + d.Set("s3_key_prefix", trail.S3KeyPrefix) + d.Set("cloud_watch_logs_role_arn", trail.CloudWatchLogsRoleArn) + d.Set("cloud_watch_logs_group_arn", trail.CloudWatchLogsLogGroupArn) + d.Set("include_global_service_events", trail.IncludeGlobalServiceEvents) + d.Set("sns_topic_name", trail.SnsTopicName) + + return nil +} + +func resourceAwsCloudTrailUpdate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).cloudtrailconn + + input := cloudtrail.UpdateTrailInput{ + Name: aws.String(d.Get("name").(string)), + } + + if d.HasChange("s3_bucket_name") { + input.S3BucketName = aws.String(d.Get("s3_bucket_name").(string)) + } + if d.HasChange("s3_key_prefix") { + input.S3KeyPrefix = aws.String(d.Get("s3_key_prefix").(string)) + } + if d.HasChange("cloud_watch_logs_role_arn") { + input.CloudWatchLogsRoleArn = aws.String(d.Get("cloud_watch_logs_role_arn").(string)) + } + if d.HasChange("cloud_watch_logs_group_arn") { + input.CloudWatchLogsLogGroupArn = aws.String(d.Get("cloud_watch_logs_group_arn").(string)) + } + if d.HasChange("include_global_service_events") { + input.IncludeGlobalServiceEvents = aws.Bool(d.Get("include_global_service_events").(bool)) + } + if d.HasChange("sns_topic_name") { + input.SnsTopicName = aws.String(d.Get("sns_topic_name").(string)) + } + + log.Printf("[DEBUG] Updating CloudTrail: %s", input) + t, err := conn.UpdateTrail(&input) + if err != nil { + return err + } + log.Printf("[DEBUG] CloudTrail updated: %s", t) + + return resourceAwsCloudTrailRead(d, meta) +} + +func resourceAwsCloudTrailDelete(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).cloudtrailconn + name := d.Get("name").(string) + + log.Printf("[DEBUG] Deleting CloudTrail: %q", name) + _, err := conn.DeleteTrail(&cloudtrail.DeleteTrailInput{ + Name: aws.String(name), + }) + + return err +}