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 }