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