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)
}