rusty_s3/credentials/
mod.rs1use std::env;
13use std::fmt::{self, Debug, Formatter};
14
15#[allow(clippy::module_name_repetitions)]
16pub use self::rotating::RotatingCredentials;
17#[cfg(feature = "full")]
18pub use self::serde::Ec2SecurityCredentialsMetadataResponse;
19use zeroize::Zeroizing;
20
21mod rotating;
22#[cfg(feature = "full")]
23mod serde;
24
25#[derive(Clone, PartialEq, Eq)]
27pub struct Credentials {
28 key: String,
29 secret: Zeroizing<String>,
30 token: Option<String>,
31}
32
33impl Credentials {
34 #[inline]
36 pub fn new(key: impl Into<String>, secret: impl Into<String>) -> Self {
37 Self::new_with_maybe_token(key.into(), secret.into(), None)
38 }
39
40 #[inline]
42 pub fn new_with_token(
43 key: impl Into<String>,
44 secret: impl Into<String>,
45 token: impl Into<String>,
46 ) -> Self {
47 Self::new_with_maybe_token(key.into(), secret.into(), Some(token.into()))
48 }
49
50 #[inline]
51 pub(super) fn new_with_maybe_token(key: String, secret: String, token: Option<String>) -> Self {
52 Self {
53 key,
54 secret: Zeroizing::new(secret),
55 token,
56 }
57 }
58
59 #[must_use]
66 pub fn from_env() -> Option<Self> {
67 let key = env::var("AWS_ACCESS_KEY_ID").ok()?;
68 let secret = env::var("AWS_SECRET_ACCESS_KEY").ok()?;
69 let token = env::var("AWS_SESSION_TOKEN").ok();
70 Some(Self::new_with_maybe_token(key, secret, token))
71 }
72
73 #[inline]
75 #[must_use]
76 pub fn key(&self) -> &str {
77 &self.key
78 }
79
80 #[inline]
82 #[must_use]
83 pub fn secret(&self) -> &str {
84 &self.secret
85 }
86
87 #[inline]
89 #[must_use]
90 pub fn token(&self) -> Option<&str> {
91 self.token.as_deref()
92 }
93}
94
95impl Debug for Credentials {
96 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
97 f.debug_struct("Credentials")
98 .field("key", &self.key)
99 .finish_non_exhaustive()
100 }
101}
102
103#[cfg(test)]
104mod tests {
105 use pretty_assertions::assert_eq;
106
107 use super::*;
108
109 #[test]
110 fn key_secret() {
111 let credentials = Credentials::new("abcd", "1234");
112 assert_eq!(credentials.key(), "abcd");
113 assert_eq!(credentials.secret(), "1234");
114 assert!(credentials.token().is_none());
115 }
116
117 #[test]
118 fn key_secret_token() {
119 let credentials = Credentials::new_with_token("abcd", "1234", "xyz");
120 assert_eq!(credentials.key(), "abcd");
121 assert_eq!(credentials.secret(), "1234");
122 assert_eq!(credentials.token(), Some("xyz"));
123 }
124
125 #[test]
126 fn debug() {
127 let credentials = Credentials::new("abcd", "1234");
128 let debug_output = format!("{credentials:?}");
129 assert_eq!(debug_output, "Credentials { key: \"abcd\", .. }");
130 }
131
132 #[test]
133 fn debug_token() {
134 let credentials = Credentials::new_with_token("abcd", "1234", "xyz");
135 let debug_output = format!("{credentials:?}");
136 assert_eq!(debug_output, "Credentials { key: \"abcd\", .. }");
137 }
138
139 #[test]
140 fn from_env() {
141 env::set_var("AWS_ACCESS_KEY_ID", "key");
142 env::set_var("AWS_SECRET_ACCESS_KEY", "secret");
143
144 let credentials = Credentials::from_env().unwrap();
145 assert_eq!(credentials.key(), "key");
146 assert_eq!(credentials.secret(), "secret");
147 assert!(credentials.token().is_none());
148
149 env::remove_var("AWS_ACCESS_KEY_ID");
150 env::remove_var("AWS_SECRET_ACCESS_KEY");
151
152 assert!(Credentials::from_env().is_none());
153 }
154}