// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may // not use this file except in compliance with the License. A copy of the // License is located at // // http://aws.amazon.com/apache2.0/ // // or in the "license" file accompanying this file. This file is distributed // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either // express or implied. See the License for the specific language governing // permissions and limitations under the License. package audit import ( "fmt" "strings" "time" "github.com/aws/amazon-ecs-agent/ecs-agent/credentials" "github.com/aws/amazon-ecs-agent/ecs-agent/logger/audit" "github.com/aws/amazon-ecs-agent/ecs-agent/logger/audit/request" log "github.com/cihub/seelog" ) const ( // getCredentialsAuditLogVersion is the version of the audit log // Version '1', the fields are: // 1. event time // 2. response code // 3. source ip address // 4. url // 5. user agent // 6. arn for the entity associated with credentials // 7. event type ('GetCredentials') // 8. version // 9. cluster // 10. container instance arn // Version '2', following fields were modified // 7. event type ('GetCredentials, GetCredentialsExecutionRole') getCredentialsAuditLogVersion = 2 ) type commonAuditLogEntryFields struct { eventTime string responseCode int srcAddr string theURL string userAgent string arn string } func (c *commonAuditLogEntryFields) string() string { return fmt.Sprintf("%s %d %s %s %s %s", c.eventTime, c.responseCode, c.srcAddr, c.theURL, c.userAgent, c.arn) } type getCredentialsAuditLogEntryFields struct { eventType string version int cluster string containerInstanceArn string } func (g *getCredentialsAuditLogEntryFields) string() string { return fmt.Sprintf("%s %d %s %s", g.eventType, g.version, g.cluster, g.containerInstanceArn) } func constructCommonAuditLogEntryFields(r request.LogRequest, httpResponseCode int) string { httpRequest := r.Request url := httpRequest.URL.Path // V2CredentialsPath contains the credentials ID, which should not be logged if strings.HasPrefix(url, credentials.V2CredentialsPath+"/") { url = credentials.V2CredentialsPath } fields := &commonAuditLogEntryFields{ eventTime: time.Now().UTC().Format(time.RFC3339), responseCode: httpResponseCode, srcAddr: populateField(httpRequest.RemoteAddr), theURL: populateField(fmt.Sprintf(`"%s"`, url)), userAgent: populateField(fmt.Sprintf(`"%s"`, httpRequest.UserAgent())), arn: populateField(r.ARN), } return fields.string() } func constructAuditLogEntryByType(eventType string, cluster string, containerInstanceArn string) string { switch eventType { case audit.GetCredentialsEventType: fields := &getCredentialsAuditLogEntryFields{ eventType: eventType, version: getCredentialsAuditLogVersion, cluster: populateField(cluster), containerInstanceArn: populateField(containerInstanceArn), } return fields.string() case audit.GetCredentialsTaskExecutionEventType: fields := &getCredentialsAuditLogEntryFields{ eventType: eventType, version: getCredentialsAuditLogVersion, cluster: populateField(cluster), containerInstanceArn: populateField(containerInstanceArn), } return fields.string() default: log.Warn(fmt.Sprintf("Unknown eventType: %s", eventType)) return "" } } func populateField(logField string) string { if logField == "" { logField = "-" } return logField }