The certificate to use for `identity` against `server`. Picks the most recently issued certificate that is active, unrevoked, and scoped to that server. Fails with a message naming the command that fixes it, because every reason this can fail is something the human who issued the delegation can put right.
(
store: &IdentityStore,
identity: &Identity,
server: Option<&str>,
)
| 98 | /// it, because every reason this can fail is something the human who issued the |
| 99 | /// delegation can put right. |
| 100 | pub fn active_for( |
| 101 | store: &IdentityStore, |
| 102 | identity: &Identity, |
| 103 | server: Option<&str>, |
| 104 | ) -> CliResult<ResolvedDelegation> { |
| 105 | // A grant handed over out of band wins. It is the mechanism for machines |
| 106 | // with no store to populate, and the freshest thing the caller has. |
| 107 | if let Some(resolved) = from_environment(identity)? { |
| 108 | return Ok(resolved); |
| 109 | } |
| 110 | |
| 111 | let all = load_for_delegate(store, identity)?; |
| 112 | |
| 113 | if all.is_empty() { |
| 114 | return Err(CliError::DelegationError { |
| 115 | message: format!( |
| 116 | "'{}' is an agent identity with no delegation certificate on this machine.\n \ |
| 117 | Issue one with: atomic identity delegate {} --can read,record,push", |
| 118 | identity.name, identity.name |
| 119 | ), |
| 120 | }); |
| 121 | } |
| 122 | |
| 123 | let resource = server |
| 124 | .map(|s| ResourceRef::new().server(s)) |
| 125 | .unwrap_or_default(); |
| 126 | |
| 127 | let usable = all.iter().find(|d| { |
| 128 | d.is_usable() |
| 129 | && d.delegation |
| 130 | .scope |
| 131 | .allows(DelegationPermission::Read, &resource) |
| 132 | }); |
| 133 | |
| 134 | if let Some(found) = usable { |
| 135 | return Ok(found.clone()); |
| 136 | } |
| 137 | |
| 138 | // Nothing usable: say precisely why, using the freshest certificate as the |
| 139 | // subject. Reporting "no delegation" when one is merely expired sends the |
| 140 | // human looking for the wrong problem. |
| 141 | let newest = &all[0]; |
| 142 | let message = match newest.status { |
| 143 | DelegationStatus::Revoked => format!( |
| 144 | "The delegation for '{}' has been revoked.\n \ |
| 145 | Issue a new one with: atomic identity delegate {} --can read,record,push", |
| 146 | identity.name, identity.name |
| 147 | ), |
| 148 | DelegationStatus::Expired => format!( |
| 149 | "The delegation for '{}' expired {}.\n \ |
| 150 | Renew it with: atomic identity agent renew {}", |
| 151 | identity.name, |
| 152 | newest |
| 153 | .delegation |
| 154 | .expires |
| 155 | .map(|e| e.format("on %Y-%m-%d").to_string()) |
| 156 | .unwrap_or_else(|| "some time ago".to_string()), |
| 157 | identity.name |
no test coverage detected