mirror of
https://github.com/imjasonh/krust
synced 2026-07-08 06:45:32 +00:00
feat: Implement registry authentication support
This implements authentication for container registries, porting functionality from go-containerregistry's authn package to Rust. Key features: - AuthConfig struct for various auth types (basic, bearer, anonymous) - Authenticator trait for pluggable auth providers - DefaultKeychain that reads Docker config files from standard locations - Support for credential helpers (docker-credential-*) - Integration with oci-distribution for registry operations The implementation checks for credentials in this order: 1. DOCKER_CONFIG environment variable 2. REGISTRY_AUTH_FILE environment variable 3. XDG_RUNTIME_DIR/containers/auth.json 4. HOME/.docker/config.json Credential helpers are supported if configured in the Docker config. This enables krust to: - Pull private base images - Push to authenticated registries - Support various auth methods (basic, token, oauth2) Closes #2 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
5acbc21b3f
commit
b6b0c71d0c
8 changed files with 898 additions and 12 deletions
76
tests/auth_integration_test.rs
Normal file
76
tests/auth_integration_test.rs
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
//! Integration tests for authentication
|
||||
|
||||
use anyhow::Result;
|
||||
use krust::auth::{AuthConfig, DefaultKeychain, Keychain};
|
||||
use std::fs;
|
||||
use tempfile::TempDir;
|
||||
|
||||
#[test]
|
||||
fn test_auth_integration_with_docker_config() -> Result<()> {
|
||||
// Create a temporary directory for Docker config
|
||||
let temp_dir = TempDir::new()?;
|
||||
let config_dir = temp_dir.path().join(".docker");
|
||||
fs::create_dir_all(&config_dir)?;
|
||||
|
||||
// Create a test Docker config
|
||||
let config_content = r#"{
|
||||
"auths": {
|
||||
"ghcr.io": {
|
||||
"auth": "dGVzdDp0ZXN0MTIz"
|
||||
},
|
||||
"docker.io": {
|
||||
"username": "testuser",
|
||||
"password": "testpass"
|
||||
}
|
||||
}
|
||||
}"#;
|
||||
|
||||
fs::write(config_dir.join("config.json"), config_content)?;
|
||||
|
||||
// Set HOME to temp directory
|
||||
std::env::set_var("HOME", temp_dir.path());
|
||||
|
||||
let keychain = DefaultKeychain::new();
|
||||
|
||||
// Test GitHub Container Registry auth
|
||||
let ghcr_auth = keychain.resolve("ghcr.io/user/image:tag")?;
|
||||
let ghcr_config = ghcr_auth.authorization()?;
|
||||
assert!(!ghcr_config.is_anonymous());
|
||||
assert_eq!(ghcr_config.auth, Some("dGVzdDp0ZXN0MTIz".to_string()));
|
||||
|
||||
// Test Docker Hub auth
|
||||
let docker_auth = keychain.resolve("docker.io/library/ubuntu:latest")?;
|
||||
let docker_config = docker_auth.authorization()?;
|
||||
assert!(!docker_config.is_anonymous());
|
||||
assert_eq!(docker_config.username, Some("testuser".to_string()));
|
||||
assert_eq!(docker_config.password, Some("testpass".to_string()));
|
||||
|
||||
// Test unknown registry returns anonymous
|
||||
let unknown_auth = keychain.resolve("unknown.registry.io/image:tag")?;
|
||||
let unknown_config = unknown_auth.authorization()?;
|
||||
assert!(unknown_config.is_anonymous());
|
||||
|
||||
// Clean up
|
||||
std::env::remove_var("HOME");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_auth_config_creation() {
|
||||
// Test anonymous
|
||||
let anon = AuthConfig::anonymous();
|
||||
assert!(anon.is_anonymous());
|
||||
|
||||
// Test basic auth
|
||||
let basic = AuthConfig::new("user".to_string(), "pass".to_string());
|
||||
assert!(!basic.is_anonymous());
|
||||
assert_eq!(basic.username, Some("user".to_string()));
|
||||
assert_eq!(basic.password, Some("pass".to_string()));
|
||||
|
||||
// Test auth header generation
|
||||
let header = basic.to_authorization_header().unwrap();
|
||||
assert!(header.is_some());
|
||||
let header_val = header.unwrap();
|
||||
assert!(header_val.starts_with("Basic "));
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue