github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/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 }