123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325 |
- <?php
- namespace Aws\CloudTrail;
- use Aws\S3\S3Client;
- use Aws\CloudTrail\Exception\CloudTrailException;
- class LogFileIterator extends \IteratorIterator
- {
-
- const DEFAULT_TRAIL_NAME = 'Default';
- const PREFIX_TEMPLATE = 'prefix/AWSLogs/account/CloudTrail/region/date/';
- const PREFIX_WILDCARD = '*';
-
- const TRAIL_NAME = 'trail_name';
- const KEY_PREFIX = 'key_prefix';
- const START_DATE = 'start_date';
- const END_DATE = 'end_date';
- const ACCOUNT_ID = 'account_id';
- const LOG_REGION = 'log_region';
-
- private $s3Client;
-
- private $s3BucketName;
-
- public static function forTrail(
- S3Client $s3Client,
- CloudTrailClient $cloudTrailClient,
- array $options = []
- ) {
- $trailName = isset($options[self::TRAIL_NAME])
- ? $options[self::TRAIL_NAME]
- : self::DEFAULT_TRAIL_NAME;
- $s3BucketName = null;
-
-
- try {
- $result = $cloudTrailClient->describeTrails([
- 'trailNameList' => [$trailName]
- ]);
- $s3BucketName = $result->search('trailList[0].S3BucketName');
- $options[self::KEY_PREFIX] = $result->search(
- 'trailList[0].S3KeyPrefix'
- );
- } catch (CloudTrailException $e) {
-
- }
-
- if (!$s3BucketName) {
- $prev = isset($e) ? $e : null;
- throw new \InvalidArgumentException('The bucket name could not '
- . 'be determined from the trail.', 0, $prev);
- }
- return new self($s3Client, $s3BucketName, $options);
- }
-
- public function __construct(
- S3Client $s3Client,
- $s3BucketName,
- array $options = []
- ) {
- $this->s3Client = $s3Client;
- $this->s3BucketName = $s3BucketName;
- parent::__construct($this->buildListObjectsIterator($options));
- }
-
-
- public function current()
- {
- if ($object = parent::current()) {
- return [
- 'Bucket' => $this->s3BucketName,
- 'Key' => $object['Key']
- ];
- }
- return false;
- }
-
- private function buildListObjectsIterator(array $options)
- {
-
- $startDate = isset($options[self::START_DATE])
- ? $this->normalizeDateValue($options[self::START_DATE])
- : null;
- $endDate = isset($options[self::END_DATE])
- ? $this->normalizeDateValue($options[self::END_DATE])
- : null;
-
- $parts = [
- 'prefix' => isset($options[self::KEY_PREFIX])
- ? $options[self::KEY_PREFIX]
- : null,
- 'account' => isset($options[self::ACCOUNT_ID])
- ? $options[self::ACCOUNT_ID]
- : self::PREFIX_WILDCARD,
- 'region' => isset($options[self::LOG_REGION])
- ? $options[self::LOG_REGION]
- : self::PREFIX_WILDCARD,
- 'date' => $this->determineDateForPrefix($startDate, $endDate),
- ];
-
-
- $candidatePrefix = ltrim(strtr(self::PREFIX_TEMPLATE, $parts), '/');
- $logKeyPrefix = $candidatePrefix;
- $index = strpos($candidatePrefix, self::PREFIX_WILDCARD);
- if ($index !== false) {
- $logKeyPrefix = substr($candidatePrefix, 0, $index);
- }
-
-
- $objectsIterator = $this->s3Client->getIterator('ListObjects', [
- 'Bucket' => $this->s3BucketName,
- 'Prefix' => $logKeyPrefix,
- ]);
-
-
- $objectsIterator = $this->applyRegexFilter(
- $objectsIterator,
- $logKeyPrefix,
- $candidatePrefix
- );
- $objectsIterator = $this->applyDateFilter(
- $objectsIterator,
- $startDate,
- $endDate
- );
- return $objectsIterator;
- }
-
- private function normalizeDateValue($date)
- {
- if (is_string($date)) {
- $date = strtotime($date);
- } elseif ($date instanceof \DateTimeInterface) {
- $date = $date->format('U');
- } elseif (!is_int($date)) {
- throw new \InvalidArgumentException('Date values must be a '
- . 'string, an int, or a DateTime object.');
- }
- return $date;
- }
-
- private function determineDateForPrefix($startDate, $endDate)
- {
-
- $dateParts = array_fill_keys(['Y', 'm', 'd'], self::PREFIX_WILDCARD);
-
-
- if ($startDate && $endDate) {
- foreach ($dateParts as $key => &$value) {
- $candidateValue = date($key, $startDate);
- if ($candidateValue === date($key, $endDate)) {
- $value = $candidateValue;
- } else {
- break;
- }
- }
- }
- return join('/', $dateParts);
- }
-
- private function applyRegexFilter(
- $objectsIterator,
- $logKeyPrefix,
- $candidatePrefix
- ) {
-
-
- if ($logKeyPrefix !== $candidatePrefix) {
-
-
- $regex = rtrim($candidatePrefix, '/' . self::PREFIX_WILDCARD) . '/';
- $regex = strtr($regex, [self::PREFIX_WILDCARD => '[^/]+']);
-
-
- if ($logKeyPrefix !== $regex) {
-
-
- $objectsIterator = new \CallbackFilterIterator(
- $objectsIterator,
- function ($object) use ($regex) {
- return preg_match("#{$regex}#", $object['Key']);
- }
- );
- }
- }
- return $objectsIterator;
- }
-
- private function applyDateFilter($objectsIterator, $startDate, $endDate)
- {
-
-
- if ($startDate || $endDate) {
- $fn = function ($object) use ($startDate, $endDate) {
- if (!preg_match('/[0-9]{8}T[0-9]{4}Z/', $object['Key'], $m)) {
- return false;
- }
- $date = strtotime($m[0]);
- return (!$startDate || $date >= $startDate)
- && (!$endDate || $date <= $endDate);
- };
- $objectsIterator = new \CallbackFilterIterator($objectsIterator, $fn);
- }
- return $objectsIterator;
- }
- }
|