Reuse native macOS Git credentials
Some checks failed
Dependency security audit / rustsec (push) Has been cancelled
Some checks failed
Dependency security audit / rustsec (push) Has been cancelled
This commit is contained in:
@@ -32,6 +32,8 @@ struct MemoryState {
|
||||
create_fault: Option<SecretStoreError>,
|
||||
retrieves: usize,
|
||||
protections: Vec<SecretProtection>,
|
||||
platform_https: Option<(String, SecretBytes)>,
|
||||
platform_https_requests: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
@@ -60,6 +62,13 @@ impl MemoryBackend {
|
||||
self.0.lock().expect("test mutex").protections.clone()
|
||||
}
|
||||
|
||||
fn with_platform_https(account: &str, password: &[u8]) -> Self {
|
||||
let backend = Self::default();
|
||||
backend.0.lock().expect("test mutex").platform_https =
|
||||
Some((account.to_owned(), SecretBytes::new(password.to_vec())));
|
||||
backend
|
||||
}
|
||||
|
||||
fn take_fault(state: &mut MemoryState) -> Result<(), SecretStoreError> {
|
||||
match state.fault.take() {
|
||||
Some(error) => Err(error),
|
||||
@@ -138,6 +147,22 @@ impl SecretStoreBackend for MemoryBackend {
|
||||
.ok_or(SecretStoreError::Missing)
|
||||
}
|
||||
|
||||
fn platform_https_git_credential(
|
||||
&self,
|
||||
endpoint: &url::Url,
|
||||
) -> Result<Option<(String, SecretBytes)>, SecretStoreError> {
|
||||
let mut state = self.0.lock().map_err(|_| SecretStoreError::Unavailable)?;
|
||||
state
|
||||
.platform_https_requests
|
||||
.push(endpoint.as_str().to_owned());
|
||||
Ok(state.platform_https.as_ref().map(|(account, password)| {
|
||||
(
|
||||
account.clone(),
|
||||
SecretBytes::new(password.expose().to_vec()),
|
||||
)
|
||||
}))
|
||||
}
|
||||
|
||||
fn lock(&self) -> Result<(), SecretStoreError> {
|
||||
let mut state = self.0.lock().map_err(|_| SecretStoreError::Unavailable)?;
|
||||
Self::take_fault(&mut state)
|
||||
@@ -149,6 +174,42 @@ impl SecretStoreBackend for MemoryBackend {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn endpoint_lookup_uses_the_native_https_credential_before_private_storage() -> TestResult {
|
||||
let backend = MemoryBackend::with_platform_https("alice", b"native-token");
|
||||
let store = store(backend.clone());
|
||||
store.unlock()?;
|
||||
let remote = GitRemote::https(
|
||||
"origin",
|
||||
"https://example.test/team/store.git",
|
||||
"server",
|
||||
"application",
|
||||
)?;
|
||||
let (server, application) = remote.https_credentials().expect("HTTPS credentials");
|
||||
store.store_https_git_credential(
|
||||
server,
|
||||
application,
|
||||
"private-account",
|
||||
SecretBytes::new(b"private-token".to_vec()),
|
||||
)?;
|
||||
let retrieves_before = backend.retrieves();
|
||||
|
||||
let credential = store.credential_for(&remote)?;
|
||||
|
||||
assert_eq!(credential.username(), "alice");
|
||||
assert_eq!(credential.password(), b"native-token");
|
||||
assert_eq!(backend.retrieves(), retrieves_before);
|
||||
assert_eq!(
|
||||
backend
|
||||
.0
|
||||
.lock()
|
||||
.expect("test mutex")
|
||||
.platform_https_requests,
|
||||
["https://example.test/team/store.git".to_owned()]
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
struct MemoryPrompt(Arc<Mutex<MemoryPromptState>>);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user