summaryrefslogtreecommitdiff
path: root/vendor/aws/aws-sdk-php/src/CloudTrail/LogRecordIterator.php
blob: 1ef6c4dc09b8bc2ec6e22c2b819c2e49076defe2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
<?php
namespace Aws\CloudTrail;

use Aws\S3\S3Client;

/**
 * The `Aws\CloudTrail\LogRecordIterator` provides an easy way to iterate over
 * log records from log files generated by AWS CloudTrail.
 *
 * CloudTrail log files contain data about your AWS API calls and are stored in
 * Amazon S3 at a predictable path based on a bucket name, a key prefix, an
 * account ID, a region, and date information. The files are gzipped and
 * contain structured data in JSON format. This class allows you to specify
 * options via its factory methods, including a date range, and emits each log
 * record from any log files that match the provided options.
 *
 * A log record containing data about an AWS API call is yielded for each
 * iteration on this object.
 */
class LogRecordIterator implements \OuterIterator
{
    /** @var LogFileReader */
    private $logFileReader;

    /** @var \Iterator */
    private $logFileIterator;

    /** @var array */
    private $records;

    /** @var int */
    private $recordIndex;

    /**
     * @param S3Client         $s3Client
     * @param CloudTrailClient $cloudTrailClient
     * @param array            $options
     *
     * @return LogRecordIterator
     */
    public static function forTrail(
        S3Client $s3Client,
        CloudTrailClient $cloudTrailClient,
        array $options = []
    ) {
        $logFileIterator = LogFileIterator::forTrail(
            $s3Client,
            $cloudTrailClient,
            $options
        );

        return new self(new LogFileReader($s3Client), $logFileIterator);
    }

    /**
     * @param S3Client $s3Client
     * @param string   $s3BucketName
     * @param array    $options
     *
     * @return LogRecordIterator
     */
    public static function forBucket(
        S3Client $s3Client,
        $s3BucketName,
        array $options = []
    ) {
        $logFileReader = new LogFileReader($s3Client);
        $iter = new LogFileIterator($s3Client, $s3BucketName, $options);

        return new self($logFileReader, $iter);
    }

    /**
     * @param S3Client $s3Client
     * @param string   $s3BucketName
     * @param string   $s3ObjectKey
     *
     * @return LogRecordIterator
     */
    public static function forFile(
        S3Client $s3Client,
        $s3BucketName,
        $s3ObjectKey
    ) {
        $logFileReader = new LogFileReader($s3Client);
        $logFileIterator = new \ArrayIterator([[
            'Bucket' => $s3BucketName,
            'Key'    => $s3ObjectKey,
        ]]);

        return new self($logFileReader, $logFileIterator);
    }

    /**
     * @param LogFileReader $logFileReader
     * @param \Iterator     $logFileIterator
     */
    public function __construct(
        LogFileReader $logFileReader,
        \Iterator $logFileIterator
    ) {
        $this->logFileReader = $logFileReader;
        $this->logFileIterator = $logFileIterator;
        $this->records = array();
        $this->recordIndex = 0;
    }

    /**
     * Returns the current log record as an array.
     *
     * @return array|false
     */
    #[\ReturnTypeWillChange]
    public function current()
    {
        return $this->valid() ? $this->records[$this->recordIndex] : false;
    }

    #[\ReturnTypeWillChange]
    public function next()
    {
        $this->recordIndex++;

        // If all the records have been exhausted, get more records from the
        // next log file.
        while (!$this->valid()) {
            $this->logFileIterator->next();
            $success = $this->loadRecordsFromCurrentLogFile();
            if (!$success) {
                // The objects iterator is exhausted as well, so stop trying
                break;
           }
        }
    }

    #[\ReturnTypeWillChange]
    public function key()
    {
        if ($logFile = $this->logFileIterator->current()) {
            return $logFile['Key'] . '.' . $this->recordIndex;
        }

        return null;
    }

    #[\ReturnTypeWillChange]
    public function valid()
    {
        return isset($this->records[$this->recordIndex]);
    }

    #[\ReturnTypeWillChange]
    public function rewind()
    {
        $this->logFileIterator->rewind();
        $this->loadRecordsFromCurrentLogFile();
    }

    #[\ReturnTypeWillChange]
    public function getInnerIterator()
    {
        return $this->logFileIterator;
    }

    /**
     * Examines the current file in the `logFileIterator` and attempts to read
     * it and load log records from it using the `logFileReader`. This method
     * expects that items pulled from the iterator will take the form:
     *
     *     [
     *         'Bucket' => '...',
     *         'Key'    => '...',
     *     ]
     *
     * @return bool Returns `true` if records were loaded and `false` if no
     *     records were found
     */
    private function loadRecordsFromCurrentLogFile()
    {
        $this->recordIndex = 0;
        $this->records = array();

        $logFile = $this->logFileIterator->current();
        if ($logFile && isset($logFile['Bucket']) && isset($logFile['Key'])) {
            $this->records = $this->logFileReader->read(
                $logFile['Bucket'],
                $logFile['Key']
            );
        }

        return (bool) $logFile;
    }
}