Source code for runway.core.providers.aws._assume_role
"""Assume an AWS IAM role."""from__future__importannotationsimportloggingfromcontextlibimportAbstractContextManagerfromdatetimeimportdatetimefromtypingimportTYPE_CHECKING,castfromtyping_extensionsimportTypedDictifTYPE_CHECKING:fromtypesimportTracebackTypefrommypy_boto3_sts.type_defsimportAssumedRoleUserTypeDef,CredentialsTypeDeffromtyping_extensionsimportSelffrom...._loggingimportRunwayLoggerfrom....contextimportRunwayContextLOGGER=cast("RunwayLogger",logging.getLogger(__name__.replace("._",".")))class_KwargsTypeDef(TypedDict):DurationSeconds:intRoleArn:strRoleSessionName:str
[docs]classAssumeRole(AbstractContextManager["AssumeRole"]):"""Context manager for assuming an AWS role."""assumed_role_user:AssumedRoleUserTypeDefcredentials:CredentialsTypeDefctx:RunwayContextduration_seconds:intrevert_on_exit:boolsession_name:str="runway"
[docs]def__init__(self,context:RunwayContext,role_arn:str|None=None,duration_seconds:int|None=None,revert_on_exit:bool=True,session_name:str|None=None,)->None:"""Instantiate class. Args: context: Runway context object. role_arn: ARN of role to be assumed. duration_seconds: Seconds that the assumed role's credentials will be valid for. (default: 3600) revert_on_exit: Whether credentials in the environment will be reverted upon exiting the context manager. session_name: Name to use for the assumed role session. (default: runway) """self.assumed_role_user={"AssumedRoleId":"","Arn":""}self.credentials={"AccessKeyId":"","Expiration":datetime.now(),"SecretAccessKey":"","SessionToken":"",}self.role_arn=role_arnself.ctx=contextself.duration_seconds=duration_secondsor3600self.revert_on_exit=revert_on_exitself.session_name=session_nameor"runway"
@propertydef_kwargs(self)->_KwargsTypeDef:"""Construct keyword arguments to pass to boto3 call."""return{"DurationSeconds":self.duration_seconds,"RoleArn":self.role_arnor"","RoleSessionName":self.session_name,}
[docs]defassume(self)->None:"""Perform role assumption."""ifnotself.role_arn:LOGGER.debug("no role to assume")returnifself.revert_on_exit:self.save_existing_iam_env_vars()sts_client=self.ctx.get_session().client("sts")LOGGER.info("assuming role %s...",self.role_arn)response=sts_client.assume_role(**self._kwargs)LOGGER.debug("sts.assume_role response: %s",response)if"Credentials"inresponse:self.assumed_role_user.update(response.get("AssumedRoleUser",cast("AssumedRoleUserTypeDef",{})))self.credentials.update(response["Credentials"])self.ctx.env.vars.update({"AWS_ACCESS_KEY_ID":response["Credentials"]["AccessKeyId"],"AWS_SECRET_ACCESS_KEY":response["Credentials"]["SecretAccessKey"],"AWS_SESSION_TOKEN":response["Credentials"]["SessionToken"],})LOGGER.verbose("updated environment with assumed credentials")else:raiseValueError("assume_role did not return Credentials")
[docs]defrestore_existing_iam_env_vars(self)->None:"""Restore backed up IAM environment variables."""ifnotself.role_arn:LOGGER.debug("no role was assumed; not reverting credentials")returnforkinself.ctx.current_aws_creds:old="OLD_"+kifself.ctx.env.vars.get(old):self.ctx.env.vars[k]=self.ctx.env.vars.pop(old)LOGGER.debug("reverted environment variables: %s",k)else:self.ctx.env.vars.pop(k,None)LOGGER.debug("removed environment variables: %s ",k)
[docs]defsave_existing_iam_env_vars(self)->None:"""Backup IAM environment variables for later restoration."""fork,vinself.ctx.current_aws_creds.items():new="OLD_"+kLOGGER.debug('saving environment variable "%s" as "%s"',k,new)self.ctx.env.vars[new]=cast("str",v)
[docs]def__enter__(self)->Self:"""Enter the context manager."""LOGGER.debug("entering aws.AssumeRole context manager...")self.assume()returnself
[docs]def__exit__(self,exc_type:type[BaseException]|None,exc_value:BaseException|None,traceback:TracebackType|None,)->None:"""Exit the context manager."""ifself.revert_on_exit:self.restore_existing_iam_env_vars()LOGGER.debug("aws.AssumeRole context manager exited")