def __post_init__(self) -> None: super().__post_init__() self._set_label_identifier = "resource" self.last_attach_timestamp = make_valid_timestamp(self.last_attach_timestamp) self.last_detach_timestamp = make_valid_timestamp(self.last_detach_timestamp) # last_activity = ( # self.last_detach_timestamp # if self.last_detach_timestamp > self.last_attach_timestamp # else self.last_attach_timestamp # ) # if self.volume_status == "available": # self.atime = self.mtime = last_activity if isinstance(self.volume_type, BaseResource): self.volume_type = self.volume_type.name
def _ctime_getter(self) -> Optional[datetime]: if "resoto:ctime" in self.tags: ctime = self.tags["resoto:ctime"] try: ctime = make_valid_timestamp(datetime.fromisoformat(ctime)) except ValueError: pass else: return ctime return self._ctime
def new(user: User) -> BaseUser: if user.password_changed_at is not None: password_age = datetime.utcnow().replace( tzinfo=timezone.utc) - make_valid_timestamp( user.password_changed_at) else: password_age = None return OneLoginUser( id=str(user.id), tags={}, name=user.username, user_id=user.id, external_id=user.external_id, email=user.email, username=user.username, firstname=user.firstname, lastname=user.lastname, distinguished_name=user.distinguished_name, phone=user.phone, company=user.company, department=user.department, title=user.title, status=user.status, member_of=user.member_of, samaccountname=user.samaccountname, userprincipalname=user.userprincipalname, group_id=user.group_id, role_ids=user.role_ids, custom_attributes=user.custom_attributes, openid_name=user.openid_name, locale_code=user.locale_code, comment=user.comment, directory_id=user.directory_id, manager_ad_id=user.manager_ad_id, trusted_idp_id=user.trusted_idp_id, manager_user_id=user.manager_user_id, activated_at=user.activated_at, created_at=user.created_at, updated_at=user.updated_at, password_changed_at=user.password_changed_at, invitation_sent_at=user.invitation_sent_at, invalid_login_attempts=user.invalid_login_attempts, last_login=user.last_login, locked_until=user.locked_until, state=user.state, ctime=user.created_at, atime=user.last_login, mtime=user.updated_at, password_age=password_age, )
def _mtime_setter(self, value: Optional[datetime]) -> None: self._mtime = make_valid_timestamp(value)
import time import copy import botocore.exceptions from datetime import date from enum import auto from resotolib.baseresources import * from resotolib.graph import Graph from resotolib.utils import make_valid_timestamp from .utils import aws_client, aws_resource, tags_as_dict from typing import ClassVar, Any, Optional, Union from dataclasses import dataclass from resotolib.logger import log default_ctime = make_valid_timestamp(date(2006, 3, 19)) # AWS public launch date # derived from https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html @dataclass(eq=False) class AWSAccount(BaseAccount): kind: ClassVar[str] = "aws_account" successor_kinds: ClassVar[Dict[str, List[str]]] = { "default": ["aws_region"], "delete": [], } account_alias: Optional[str] = "" role: Optional[str] = None users: Optional[int] = 0 groups: Optional[int] = 0 account_mfa_enabled: Optional[int] = 0
def main(): if ArgumentParser.args.aws_role and ArgumentParser.args.aws_account: accounts = [ AWSAccount(aws_account_id, {}, role=ArgumentParser.args.aws_role) for aws_account_id in ArgumentParser.args.aws_account ] else: accounts = [AWSAccount(current_account_id(), {})] if len(accounts) != 1: log.error("This tool only supports a single account at a time") sys.exit(1) account = accounts[0] session = aws_session(account.id, account.role) client = session.client("s3") bucket = ArgumentParser.args.aws_s3_bucket prefix = ArgumentParser.args.aws_s3_prefix mtime = ( make_valid_timestamp(datetime.fromisoformat(ArgumentParser.args.aws_s3_mtime)) if ArgumentParser.args.aws_s3_mtime else None ) is_truncated = True max_keys = 500 key_marker = None version_id_marker = None while is_truncated is True: if key_marker and version_id_marker: version_list = client.list_object_versions( Bucket=bucket, MaxKeys=max_keys, Prefix=prefix, KeyMarker=key_marker, VersionIdMarker=version_id_marker, ) elif key_marker: version_list = client.list_object_versions( Bucket=bucket, MaxKeys=max_keys, Prefix=prefix, KeyMarker=key_marker ) else: version_list = client.list_object_versions( Bucket=bucket, MaxKeys=max_keys, Prefix=prefix ) is_truncated = version_list.get("IsTruncated", False) key_marker = version_list.get("NextKeyMarker") version_id_marker = version_list.get("NextVersionIdMarker") delete_objects = [] versions = version_list.get("Versions", []) versions.extend(version_list.get("DeleteMarkers", [])) for v in versions: object_version = v["VersionId"] object_key = v["Key"] # object_size = v["Size"] object_mtime = make_valid_timestamp(v["LastModified"]) if mtime and object_mtime > mtime: log.debug( f"Object {object_key} with mtime {object_mtime} newer than mtime {mtime}" ) continue if ( ArgumentParser.args.aws_s3_pattern and bool(re.search(ArgumentParser.args.aws_s3_pattern, str(object_key))) is False ): log.debug( f"Object {object_key} does not match {ArgumentParser.args.aws_s3_pattern}" ) continue log.info( ( f"Object {object_key} with version {object_version} and mtime" f" {object_mtime} matches {ArgumentParser.args.aws_s3_pattern}" ) ) delete_objects.append({"VersionId": object_version, "Key": object_key}) try: if len(delete_objects) > 0: str_delete_objects = "\n".join([do["Key"] for do in delete_objects]) if ArgumentParser.args.aws_s3_yes is True: confirm_delete = True else: confirm_delete = button_dialog( title=f"Delete {len(delete_objects)} S3 objects?", text=f"Really delete these objects?\n{str_delete_objects}", buttons=[("Yes", True), ("No", False), ("Abort", None)], ).run() if confirm_delete is None: sys.exit(0) elif confirm_delete is True: response = client.delete_objects( Bucket=bucket, Delete={"Objects": delete_objects} ) log.info(f"Delete response {response}") except Exception: log.exception("Something went wrong trying to delete")