fn fetch_role_arn()

in src/vtok_agent/src/imds.rs [199:240]


    fn fetch_role_arn(token: &str) -> Result<String, Error> {
        if let Ok(role_arn) = Self::fetch_instance_tag(token, INSTANCE_ROLE_ARN_TAG) {
            return Ok(role_arn);
        }

        let role_name = Self::fetch_role_name(token)?;

        let output = Command::new("aws")
            .arg("iam")
            .arg("get-role")
            .arg("--role-name")
            .arg(format!("{}", role_name))
            .output()
            .map_err(Error::IoError)?;
        // If error, fallback to use the IMDS info to get the IAM role arn.
        // Note: This logic would not work for IAM roles which include paths.
        if !output.status.success() {
            warn!("Cannot fetch IAM role arn using the AWS CLI iam get-role command. Falling back to using IMDS.");
            warn!("For IAM roles with paths included, please add the IAM policy permission for iam:GetRole as per documentation - https://docs.aws.amazon.com/enclaves/latest/user/nitro-enclave-refapp.html.");
            let profile_arn =
                serde_json::from_str::<IamInfo>(&Self::fetch("/latest/meta-data/iam/info", token)?)
                    .and_then(|info| Ok(info.instance_profile_arn))
                    .map_err(Error::ParseError)?;

            let role_arn = profile_arn
                .split(":")
                .map(|word| match word.find("instance-profile/") {
                    Some(_) => format!("role/{}", role_name),
                    None => word.to_string(),
                })
                .collect::<Vec<String>>()
                .join(":");

            return Ok(role_arn);
        }

        let iam_role_info: IamRoleInfo =
            serde_json::from_str(&String::from_utf8(output.stdout).map_err(Error::Utf8Error)?)
                .map_err(Error::ParseError)?;

        Ok(iam_role_info.role.arn)
    }