github.com/andresvia/terraform@v0.6.15-0.20160412045437-d51c75946785/builtin/providers/aws/resource_aws_cloudtrail.go (about)

     1  package aws
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  
     7  	"github.com/aws/aws-sdk-go/aws"
     8  	"github.com/aws/aws-sdk-go/service/cloudtrail"
     9  	"github.com/hashicorp/terraform/helper/schema"
    10  )
    11  
    12  func resourceAwsCloudTrail() *schema.Resource {
    13  	return &schema.Resource{
    14  		Create: resourceAwsCloudTrailCreate,
    15  		Read:   resourceAwsCloudTrailRead,
    16  		Update: resourceAwsCloudTrailUpdate,
    17  		Delete: resourceAwsCloudTrailDelete,
    18  
    19  		Schema: map[string]*schema.Schema{
    20  			"name": &schema.Schema{
    21  				Type:     schema.TypeString,
    22  				Required: true,
    23  				ForceNew: true,
    24  			},
    25  			"enable_logging": &schema.Schema{
    26  				Type:     schema.TypeBool,
    27  				Optional: true,
    28  				Default:  true,
    29  			},
    30  			"s3_bucket_name": &schema.Schema{
    31  				Type:     schema.TypeString,
    32  				Required: true,
    33  			},
    34  			"s3_key_prefix": &schema.Schema{
    35  				Type:     schema.TypeString,
    36  				Optional: true,
    37  			},
    38  			"cloud_watch_logs_role_arn": &schema.Schema{
    39  				Type:     schema.TypeString,
    40  				Optional: true,
    41  			},
    42  			"cloud_watch_logs_group_arn": &schema.Schema{
    43  				Type:     schema.TypeString,
    44  				Optional: true,
    45  			},
    46  			"include_global_service_events": &schema.Schema{
    47  				Type:     schema.TypeBool,
    48  				Optional: true,
    49  				Default:  true,
    50  			},
    51  			"is_multi_region_trail": &schema.Schema{
    52  				Type:     schema.TypeBool,
    53  				Optional: true,
    54  				Default:  false,
    55  			},
    56  			"sns_topic_name": &schema.Schema{
    57  				Type:     schema.TypeString,
    58  				Optional: true,
    59  			},
    60  			"enable_log_file_validation": &schema.Schema{
    61  				Type:     schema.TypeBool,
    62  				Optional: true,
    63  				Default:  false,
    64  			},
    65  			"kms_key_id": &schema.Schema{
    66  				Type:     schema.TypeString,
    67  				Optional: true,
    68  			},
    69  			"home_region": &schema.Schema{
    70  				Type:     schema.TypeString,
    71  				Computed: true,
    72  			},
    73  			"arn": &schema.Schema{
    74  				Type:     schema.TypeString,
    75  				Computed: true,
    76  			},
    77  			"tags": tagsSchema(),
    78  		},
    79  	}
    80  }
    81  
    82  func resourceAwsCloudTrailCreate(d *schema.ResourceData, meta interface{}) error {
    83  	conn := meta.(*AWSClient).cloudtrailconn
    84  
    85  	input := cloudtrail.CreateTrailInput{
    86  		Name:         aws.String(d.Get("name").(string)),
    87  		S3BucketName: aws.String(d.Get("s3_bucket_name").(string)),
    88  	}
    89  
    90  	if v, ok := d.GetOk("cloud_watch_logs_group_arn"); ok {
    91  		input.CloudWatchLogsLogGroupArn = aws.String(v.(string))
    92  	}
    93  	if v, ok := d.GetOk("cloud_watch_logs_role_arn"); ok {
    94  		input.CloudWatchLogsRoleArn = aws.String(v.(string))
    95  	}
    96  	if v, ok := d.GetOk("include_global_service_events"); ok {
    97  		input.IncludeGlobalServiceEvents = aws.Bool(v.(bool))
    98  	}
    99  	if v, ok := d.GetOk("is_multi_region_trail"); ok {
   100  		input.IsMultiRegionTrail = aws.Bool(v.(bool))
   101  	}
   102  	if v, ok := d.GetOk("enable_log_file_validation"); ok {
   103  		input.EnableLogFileValidation = aws.Bool(v.(bool))
   104  	}
   105  	if v, ok := d.GetOk("kms_key_id"); ok {
   106  		input.KmsKeyId = aws.String(v.(string))
   107  	}
   108  	if v, ok := d.GetOk("s3_key_prefix"); ok {
   109  		input.S3KeyPrefix = aws.String(v.(string))
   110  	}
   111  	if v, ok := d.GetOk("sns_topic_name"); ok {
   112  		input.SnsTopicName = aws.String(v.(string))
   113  	}
   114  
   115  	t, err := conn.CreateTrail(&input)
   116  	if err != nil {
   117  		return err
   118  	}
   119  
   120  	log.Printf("[DEBUG] CloudTrail created: %s", t)
   121  
   122  	d.Set("arn", *t.TrailARN)
   123  	d.SetId(*t.Name)
   124  
   125  	// AWS CloudTrail sets newly-created trails to false.
   126  	if v, ok := d.GetOk("enable_logging"); ok && v.(bool) {
   127  		err := cloudTrailSetLogging(conn, v.(bool), d.Id())
   128  		if err != nil {
   129  			return err
   130  		}
   131  	}
   132  
   133  	return resourceAwsCloudTrailUpdate(d, meta)
   134  }
   135  
   136  func resourceAwsCloudTrailRead(d *schema.ResourceData, meta interface{}) error {
   137  	conn := meta.(*AWSClient).cloudtrailconn
   138  
   139  	name := d.Get("name").(string)
   140  	input := cloudtrail.DescribeTrailsInput{
   141  		TrailNameList: []*string{
   142  			aws.String(name),
   143  		},
   144  	}
   145  	resp, err := conn.DescribeTrails(&input)
   146  	if err != nil {
   147  		return err
   148  	}
   149  
   150  	// CloudTrail does not return a NotFound error in the event that the Trail
   151  	// you're looking for is not found. Instead, it's simply not in the list.
   152  	var trail *cloudtrail.Trail
   153  	for _, c := range resp.TrailList {
   154  		if d.Id() == *c.Name {
   155  			trail = c
   156  		}
   157  	}
   158  
   159  	if trail == nil {
   160  		log.Printf("[WARN] CloudTrail (%s) not found", name)
   161  		d.SetId("")
   162  		return nil
   163  	}
   164  
   165  	log.Printf("[DEBUG] CloudTrail received: %s", trail)
   166  
   167  	d.Set("name", trail.Name)
   168  	d.Set("s3_bucket_name", trail.S3BucketName)
   169  	d.Set("s3_key_prefix", trail.S3KeyPrefix)
   170  	d.Set("cloud_watch_logs_role_arn", trail.CloudWatchLogsRoleArn)
   171  	d.Set("cloud_watch_logs_group_arn", trail.CloudWatchLogsLogGroupArn)
   172  	d.Set("include_global_service_events", trail.IncludeGlobalServiceEvents)
   173  	d.Set("is_multi_region_trail", trail.IsMultiRegionTrail)
   174  	d.Set("sns_topic_name", trail.SnsTopicName)
   175  	d.Set("enable_log_file_validation", trail.LogFileValidationEnabled)
   176  
   177  	// TODO: Make it possible to use KMS Key names, not just ARNs
   178  	// In order to test it properly this PR needs to be merged 1st:
   179  	// https://github.com/hashicorp/terraform/pull/3928
   180  	d.Set("kms_key_id", trail.KmsKeyId)
   181  
   182  	d.Set("arn", trail.TrailARN)
   183  	d.Set("home_region", trail.HomeRegion)
   184  
   185  	// Get tags
   186  	req := &cloudtrail.ListTagsInput{
   187  		ResourceIdList: []*string{trail.TrailARN},
   188  	}
   189  
   190  	tagsOut, err := conn.ListTags(req)
   191  	if err != nil {
   192  		return err
   193  	}
   194  	log.Printf("[DEBUG] Received CloudTrail tags: %s", tagsOut)
   195  
   196  	var tags []*cloudtrail.Tag
   197  	if tagsOut.ResourceTagList != nil && len(tagsOut.ResourceTagList) > 0 {
   198  		tags = tagsOut.ResourceTagList[0].TagsList
   199  	}
   200  
   201  	if err := d.Set("tags", tagsToMapCloudtrail(tags)); err != nil {
   202  		return err
   203  	}
   204  
   205  	logstatus, err := cloudTrailGetLoggingStatus(conn, trail.Name)
   206  	if err != nil {
   207  		return err
   208  	}
   209  	d.Set("enable_logging", logstatus)
   210  
   211  	return nil
   212  }
   213  
   214  func resourceAwsCloudTrailUpdate(d *schema.ResourceData, meta interface{}) error {
   215  	conn := meta.(*AWSClient).cloudtrailconn
   216  
   217  	input := cloudtrail.UpdateTrailInput{
   218  		Name: aws.String(d.Get("name").(string)),
   219  	}
   220  
   221  	if d.HasChange("s3_bucket_name") {
   222  		input.S3BucketName = aws.String(d.Get("s3_bucket_name").(string))
   223  	}
   224  	if d.HasChange("s3_key_prefix") {
   225  		input.S3KeyPrefix = aws.String(d.Get("s3_key_prefix").(string))
   226  	}
   227  	if d.HasChange("cloud_watch_logs_role_arn") {
   228  		input.CloudWatchLogsRoleArn = aws.String(d.Get("cloud_watch_logs_role_arn").(string))
   229  	}
   230  	if d.HasChange("cloud_watch_logs_group_arn") {
   231  		input.CloudWatchLogsLogGroupArn = aws.String(d.Get("cloud_watch_logs_group_arn").(string))
   232  	}
   233  	if d.HasChange("include_global_service_events") {
   234  		input.IncludeGlobalServiceEvents = aws.Bool(d.Get("include_global_service_events").(bool))
   235  	}
   236  	if d.HasChange("is_multi_region_trail") {
   237  		input.IsMultiRegionTrail = aws.Bool(d.Get("is_multi_region_trail").(bool))
   238  	}
   239  	if d.HasChange("enable_log_file_validation") {
   240  		input.EnableLogFileValidation = aws.Bool(d.Get("enable_log_file_validation").(bool))
   241  	}
   242  	if d.HasChange("kms_key_id") {
   243  		input.KmsKeyId = aws.String(d.Get("kms_key_id").(string))
   244  	}
   245  	if d.HasChange("sns_topic_name") {
   246  		input.SnsTopicName = aws.String(d.Get("sns_topic_name").(string))
   247  	}
   248  
   249  	log.Printf("[DEBUG] Updating CloudTrail: %s", input)
   250  	t, err := conn.UpdateTrail(&input)
   251  	if err != nil {
   252  		return err
   253  	}
   254  
   255  	if d.HasChange("tags") {
   256  		err := setTagsCloudtrail(conn, d)
   257  		if err != nil {
   258  			return err
   259  		}
   260  	}
   261  
   262  	if d.HasChange("enable_logging") {
   263  		log.Printf("[DEBUG] Updating logging on CloudTrail: %s", input)
   264  		err := cloudTrailSetLogging(conn, d.Get("enable_logging").(bool), *input.Name)
   265  		if err != nil {
   266  			return err
   267  		}
   268  	}
   269  
   270  	log.Printf("[DEBUG] CloudTrail updated: %s", t)
   271  
   272  	return resourceAwsCloudTrailRead(d, meta)
   273  }
   274  
   275  func resourceAwsCloudTrailDelete(d *schema.ResourceData, meta interface{}) error {
   276  	conn := meta.(*AWSClient).cloudtrailconn
   277  	name := d.Get("name").(string)
   278  
   279  	log.Printf("[DEBUG] Deleting CloudTrail: %q", name)
   280  	_, err := conn.DeleteTrail(&cloudtrail.DeleteTrailInput{
   281  		Name: aws.String(name),
   282  	})
   283  
   284  	return err
   285  }
   286  
   287  func cloudTrailGetLoggingStatus(conn *cloudtrail.CloudTrail, id *string) (bool, error) {
   288  	GetTrailStatusOpts := &cloudtrail.GetTrailStatusInput{
   289  		Name: id,
   290  	}
   291  	resp, err := conn.GetTrailStatus(GetTrailStatusOpts)
   292  	if err != nil {
   293  		return false, fmt.Errorf("Error retrieving logging status of CloudTrail (%s): %s", *id, err)
   294  	}
   295  
   296  	return *resp.IsLogging, err
   297  }
   298  
   299  func cloudTrailSetLogging(conn *cloudtrail.CloudTrail, enabled bool, id string) error {
   300  	if enabled {
   301  		log.Printf(
   302  			"[DEBUG] Starting logging on CloudTrail (%s)",
   303  			id)
   304  		StartLoggingOpts := &cloudtrail.StartLoggingInput{
   305  			Name: aws.String(id),
   306  		}
   307  		if _, err := conn.StartLogging(StartLoggingOpts); err != nil {
   308  			return fmt.Errorf(
   309  				"Error starting logging on CloudTrail (%s): %s",
   310  				id, err)
   311  		}
   312  	} else {
   313  		log.Printf(
   314  			"[DEBUG] Stopping logging on CloudTrail (%s)",
   315  			id)
   316  		StopLoggingOpts := &cloudtrail.StopLoggingInput{
   317  			Name: aws.String(id),
   318  		}
   319  		if _, err := conn.StopLogging(StopLoggingOpts); err != nil {
   320  			return fmt.Errorf(
   321  				"Error stopping logging on CloudTrail (%s): %s",
   322  				id, err)
   323  		}
   324  	}
   325  
   326  	return nil
   327  }