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 }