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