mirror of
https://github.com/imjasonh/krust
synced 2026-07-22 16:01:49 +00:00
feat: Add RegistryAuth::from_default() convenience methods
- Add from_default() and from_default_str() methods to RegistryAuth - These methods automatically resolve auth from Docker config and credential helpers - Update example to demonstrate both explicit and auto auth approaches - Simplify krust's auth wrapper to use the new convenience method - Fix test environment variable pollution 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
a6ae83c3b2
commit
672ada3dd2
9 changed files with 148 additions and 239 deletions
|
|
@ -1,11 +1,10 @@
|
||||||
//! Simple authentication wrapper using oci-distribution's credential helper
|
//! Simple authentication wrapper using oci-distribution's credential helper
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use oci_distribution::credential_helper::resolve_docker_auth;
|
|
||||||
use oci_distribution::secrets::RegistryAuth;
|
use oci_distribution::secrets::RegistryAuth;
|
||||||
|
|
||||||
/// Resolve authentication for a given resource using Docker config and credential helpers
|
/// Resolve authentication for a given resource using Docker config and credential helpers
|
||||||
pub fn resolve_auth(resource: &str) -> Result<RegistryAuth> {
|
pub fn resolve_auth(resource: &str) -> Result<RegistryAuth> {
|
||||||
resolve_docker_auth(resource)
|
RegistryAuth::from_default_str(resource)
|
||||||
.map_err(|e| anyhow::anyhow!("Failed to resolve auth: {}", e))
|
.map_err(|e| anyhow::anyhow!("Failed to resolve auth: {}", e))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -91,21 +91,30 @@ fn test_resolve_auth_bearer_token() -> Result<()> {
|
||||||
|
|
||||||
fs::write(&config_path, config)?;
|
fs::write(&config_path, config)?;
|
||||||
|
|
||||||
// Save current env var
|
// Save current env vars
|
||||||
let old_val = env::var("DOCKER_CONFIG").ok();
|
let old_docker_config = env::var("DOCKER_CONFIG").ok();
|
||||||
|
let old_registry_auth = env::var("REGISTRY_AUTH_FILE").ok();
|
||||||
|
|
||||||
|
// Set our test config and clear other env vars
|
||||||
env::set_var("DOCKER_CONFIG", tmp_dir.path());
|
env::set_var("DOCKER_CONFIG", tmp_dir.path());
|
||||||
|
env::remove_var("REGISTRY_AUTH_FILE");
|
||||||
|
|
||||||
// Should resolve to bearer auth
|
// Should resolve to bearer auth
|
||||||
let auth = resolve_auth("ghcr.io/user/image")?;
|
let auth = resolve_auth("ghcr.io/user/image")?;
|
||||||
assert!(matches!(auth, RegistryAuth::Bearer(token)
|
assert!(matches!(auth, RegistryAuth::Bearer(token)
|
||||||
if token == "test-bearer-token"));
|
if token == "test-bearer-token"));
|
||||||
|
|
||||||
// Restore env var
|
// Restore env vars
|
||||||
if let Some(val) = old_val {
|
if let Some(val) = old_docker_config {
|
||||||
env::set_var("DOCKER_CONFIG", val);
|
env::set_var("DOCKER_CONFIG", val);
|
||||||
} else {
|
} else {
|
||||||
env::remove_var("DOCKER_CONFIG");
|
env::remove_var("DOCKER_CONFIG");
|
||||||
}
|
}
|
||||||
|
if let Some(val) = old_registry_auth {
|
||||||
|
env::set_var("REGISTRY_AUTH_FILE", val);
|
||||||
|
} else {
|
||||||
|
env::remove_var("REGISTRY_AUTH_FILE");
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
88
vendor/oci-distribution/examples/auto_auth_demo.rs
vendored
Normal file
88
vendor/oci-distribution/examples/auto_auth_demo.rs
vendored
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
use oci_distribution::client::{ClientConfig, Client};
|
||||||
|
use oci_distribution::secrets::RegistryAuth;
|
||||||
|
use oci_distribution::Reference;
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
// Setup logging
|
||||||
|
tracing_subscriber::fmt()
|
||||||
|
.with_env_filter(
|
||||||
|
tracing_subscriber::EnvFilter::from_default_env()
|
||||||
|
.add_directive("oci_distribution=debug".parse()?)
|
||||||
|
)
|
||||||
|
.init();
|
||||||
|
|
||||||
|
// Create a client
|
||||||
|
let config = ClientConfig::default();
|
||||||
|
let client = Client::new(config);
|
||||||
|
|
||||||
|
// Example 1: Using the new from_default() method
|
||||||
|
println!("Example 1: Using RegistryAuth::from_default()");
|
||||||
|
let alpine_ref = Reference::try_from("docker.io/library/alpine:latest")?;
|
||||||
|
let auth = RegistryAuth::from_default(&alpine_ref)?;
|
||||||
|
match client.pull_manifest(&alpine_ref, &auth).await {
|
||||||
|
Ok((manifest, digest)) => {
|
||||||
|
println!("Successfully pulled manifest for alpine:latest");
|
||||||
|
println!("Digest: {}", digest);
|
||||||
|
|
||||||
|
// Handle the manifest enum
|
||||||
|
match manifest {
|
||||||
|
oci_distribution::manifest::OciManifest::Image(img) => {
|
||||||
|
println!("Config digest: {}", img.config.digest);
|
||||||
|
}
|
||||||
|
oci_distribution::manifest::OciManifest::ImageIndex(_) => {
|
||||||
|
println!("Got an image index manifest");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
println!("Failed to pull alpine:latest: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Example 2: Using the convenience *_auto methods (same result, less code)
|
||||||
|
println!("\nExample 2: Using pull_manifest_auto() convenience method");
|
||||||
|
let busybox_ref = Reference::try_from("docker.io/library/busybox:latest")?;
|
||||||
|
match client.pull_manifest_auto(&busybox_ref).await {
|
||||||
|
Ok((manifest, digest)) => {
|
||||||
|
println!("Successfully pulled manifest for busybox:latest");
|
||||||
|
println!("Digest: {}", digest);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
println!("Failed to pull busybox:latest: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Example 3: Get platforms using auto auth
|
||||||
|
println!("\nExample 3: Getting platforms with automatic auth");
|
||||||
|
match client.get_image_platforms_auto(&busybox_ref).await {
|
||||||
|
Ok(platforms) => {
|
||||||
|
println!("Busybox platforms:");
|
||||||
|
for (arch, os) in platforms {
|
||||||
|
println!(" - {}/{}", os, arch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
println!("Failed to get platforms: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Example 4: Using from_default_str for non-Reference strings
|
||||||
|
println!("\nExample 4: Using RegistryAuth::from_default_str()");
|
||||||
|
let auth = RegistryAuth::from_default_str("gcr.io/example/image:tag")?;
|
||||||
|
println!("Resolved auth for gcr.io: {:?}", auth);
|
||||||
|
|
||||||
|
// If you have credentials configured for private registries,
|
||||||
|
// both approaches will automatically use them:
|
||||||
|
//
|
||||||
|
// let private_ref = Reference::try_from("ghcr.io/myuser/myimage:latest")?;
|
||||||
|
//
|
||||||
|
// // Option 1: Explicit auth resolution
|
||||||
|
// let auth = RegistryAuth::from_default(&private_ref)?;
|
||||||
|
// let result = client.pull(&private_ref, &auth, vec![]).await?;
|
||||||
|
//
|
||||||
|
// // Option 2: Using the convenience method
|
||||||
|
// let result = client.pull_auto(&private_ref).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
47
vendor/oci-distribution/examples/wasm/cli.rs
vendored
47
vendor/oci-distribution/examples/wasm/cli.rs
vendored
|
|
@ -1,47 +0,0 @@
|
||||||
use clap::{Parser, Subcommand};
|
|
||||||
|
|
||||||
/// Pull a WebAssembly module from a OCI container registry
|
|
||||||
#[derive(Parser, Debug)]
|
|
||||||
#[clap(author, version, about, long_about = None)]
|
|
||||||
pub(crate) struct Cli {
|
|
||||||
/// Enable verbose mode
|
|
||||||
#[clap(short, long)]
|
|
||||||
pub verbose: bool,
|
|
||||||
|
|
||||||
/// Perform anonymous operation, by default the tool tries to reuse the docker credentials read
|
|
||||||
/// from the default docker file
|
|
||||||
#[clap(short, long)]
|
|
||||||
pub anonymous: bool,
|
|
||||||
|
|
||||||
/// Pull image from registry using HTTP instead of HTTPS
|
|
||||||
#[clap(short, long)]
|
|
||||||
pub insecure: bool,
|
|
||||||
|
|
||||||
#[clap(subcommand)]
|
|
||||||
pub command: Commands,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Subcommand)]
|
|
||||||
pub(crate) enum Commands {
|
|
||||||
#[clap(arg_required_else_help = true)]
|
|
||||||
Pull {
|
|
||||||
/// Write contents to file
|
|
||||||
#[clap(short, long)]
|
|
||||||
output: String,
|
|
||||||
|
|
||||||
/// Name of the image to pull
|
|
||||||
image: String,
|
|
||||||
},
|
|
||||||
#[clap(arg_required_else_help = true)]
|
|
||||||
Push {
|
|
||||||
/// OCI Annotations to be added to the manifest
|
|
||||||
#[clap(short, long, required(false))]
|
|
||||||
annotations: Vec<String>,
|
|
||||||
|
|
||||||
/// Wasm file to push
|
|
||||||
module: String,
|
|
||||||
|
|
||||||
/// Name of the image to pull
|
|
||||||
image: String,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
111
vendor/oci-distribution/examples/wasm/main.rs
vendored
111
vendor/oci-distribution/examples/wasm/main.rs
vendored
|
|
@ -1,111 +0,0 @@
|
||||||
use oci_distribution::{annotations, secrets::RegistryAuth, Client, Reference};
|
|
||||||
|
|
||||||
use docker_credential::{CredentialRetrievalError, DockerCredential};
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use tracing::{debug, warn};
|
|
||||||
use tracing_subscriber::prelude::*;
|
|
||||||
use tracing_subscriber::{fmt, EnvFilter};
|
|
||||||
|
|
||||||
mod cli;
|
|
||||||
use clap::Parser;
|
|
||||||
use cli::Cli;
|
|
||||||
|
|
||||||
mod pull;
|
|
||||||
use pull::pull_wasm;
|
|
||||||
|
|
||||||
mod push;
|
|
||||||
use push::push_wasm;
|
|
||||||
|
|
||||||
fn build_auth(reference: &Reference, cli: &Cli) -> RegistryAuth {
|
|
||||||
let server = reference
|
|
||||||
.resolve_registry()
|
|
||||||
.strip_suffix('/')
|
|
||||||
.unwrap_or_else(|| reference.resolve_registry());
|
|
||||||
|
|
||||||
if cli.anonymous {
|
|
||||||
return RegistryAuth::Anonymous;
|
|
||||||
}
|
|
||||||
|
|
||||||
match docker_credential::get_credential(server) {
|
|
||||||
Err(CredentialRetrievalError::ConfigNotFound) => RegistryAuth::Anonymous,
|
|
||||||
Err(CredentialRetrievalError::NoCredentialConfigured) => RegistryAuth::Anonymous,
|
|
||||||
Err(e) => panic!("Error handling docker configuration file: {}", e),
|
|
||||||
Ok(DockerCredential::UsernamePassword(username, password)) => {
|
|
||||||
debug!("Found docker credentials");
|
|
||||||
RegistryAuth::Basic(username, password)
|
|
||||||
}
|
|
||||||
Ok(DockerCredential::IdentityToken(_)) => {
|
|
||||||
warn!("Cannot use contents of docker config, identity token not supported. Using anonymous auth");
|
|
||||||
RegistryAuth::Anonymous
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build_client_config(cli: &Cli) -> oci_distribution::client::ClientConfig {
|
|
||||||
let protocol = if cli.insecure {
|
|
||||||
oci_distribution::client::ClientProtocol::Http
|
|
||||||
} else {
|
|
||||||
oci_distribution::client::ClientProtocol::Https
|
|
||||||
};
|
|
||||||
|
|
||||||
oci_distribution::client::ClientConfig {
|
|
||||||
protocol,
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::main]
|
|
||||||
pub async fn main() {
|
|
||||||
let cli = Cli::parse();
|
|
||||||
|
|
||||||
// setup logging
|
|
||||||
let level_filter = if cli.verbose { "debug" } else { "info" };
|
|
||||||
let filter_layer = EnvFilter::new(level_filter);
|
|
||||||
tracing_subscriber::registry()
|
|
||||||
.with(filter_layer)
|
|
||||||
.with(fmt::layer().with_writer(std::io::stderr))
|
|
||||||
.init();
|
|
||||||
|
|
||||||
let client_config = build_client_config(&cli);
|
|
||||||
let mut client = Client::new(client_config);
|
|
||||||
|
|
||||||
match &cli.command {
|
|
||||||
crate::cli::Commands::Pull { output, image } => {
|
|
||||||
let reference: Reference = image.parse().expect("Not a valid image reference");
|
|
||||||
let auth = build_auth(&reference, &cli);
|
|
||||||
pull_wasm(&mut client, &auth, &reference, output).await;
|
|
||||||
}
|
|
||||||
crate::cli::Commands::Push {
|
|
||||||
module,
|
|
||||||
image,
|
|
||||||
annotations,
|
|
||||||
} => {
|
|
||||||
let reference: Reference = image.parse().expect("Not a valid image reference");
|
|
||||||
let auth = build_auth(&reference, &cli);
|
|
||||||
|
|
||||||
let annotations = if annotations.is_empty() {
|
|
||||||
let mut values: HashMap<String, String> = HashMap::new();
|
|
||||||
values.insert(
|
|
||||||
annotations::ORG_OPENCONTAINERS_IMAGE_TITLE.to_string(),
|
|
||||||
module.clone(),
|
|
||||||
);
|
|
||||||
Some(values)
|
|
||||||
} else {
|
|
||||||
let mut values: HashMap<String, String> = HashMap::new();
|
|
||||||
for annotation in annotations {
|
|
||||||
let tmp: Vec<_> = annotation.splitn(2, '=').collect();
|
|
||||||
if tmp.len() == 2 {
|
|
||||||
values.insert(String::from(tmp[0]), String::from(tmp[1]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
values
|
|
||||||
.entry(annotations::ORG_OPENCONTAINERS_IMAGE_TITLE.to_string())
|
|
||||||
.or_insert_with(|| module.clone());
|
|
||||||
|
|
||||||
Some(values)
|
|
||||||
};
|
|
||||||
|
|
||||||
push_wasm(&mut client, &auth, &reference, module, annotations).await;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
26
vendor/oci-distribution/examples/wasm/pull.rs
vendored
26
vendor/oci-distribution/examples/wasm/pull.rs
vendored
|
|
@ -1,26 +0,0 @@
|
||||||
use oci_distribution::{manifest, secrets::RegistryAuth, Client, Reference};
|
|
||||||
use tracing::info;
|
|
||||||
|
|
||||||
pub(crate) async fn pull_wasm(
|
|
||||||
client: &mut Client,
|
|
||||||
auth: &RegistryAuth,
|
|
||||||
reference: &Reference,
|
|
||||||
output: &str,
|
|
||||||
) {
|
|
||||||
info!(?reference, ?output, "pulling wasm module");
|
|
||||||
|
|
||||||
let image_content = client
|
|
||||||
.pull(reference, auth, vec![manifest::WASM_LAYER_MEDIA_TYPE])
|
|
||||||
.await
|
|
||||||
.expect("Cannot pull Wasm module")
|
|
||||||
.layers
|
|
||||||
.into_iter()
|
|
||||||
.next()
|
|
||||||
.map(|layer| layer.data)
|
|
||||||
.expect("No data found");
|
|
||||||
|
|
||||||
async_std::fs::write(output, image_content)
|
|
||||||
.await
|
|
||||||
.expect("Cannot write to file");
|
|
||||||
println!("Wasm module successfully written to {}", output);
|
|
||||||
}
|
|
||||||
44
vendor/oci-distribution/examples/wasm/push.rs
vendored
44
vendor/oci-distribution/examples/wasm/push.rs
vendored
|
|
@ -1,44 +0,0 @@
|
||||||
use oci_distribution::{
|
|
||||||
client::{Config, ImageLayer},
|
|
||||||
manifest,
|
|
||||||
secrets::RegistryAuth,
|
|
||||||
Client, Reference,
|
|
||||||
};
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use tracing::info;
|
|
||||||
|
|
||||||
pub(crate) async fn push_wasm(
|
|
||||||
client: &mut Client,
|
|
||||||
auth: &RegistryAuth,
|
|
||||||
reference: &Reference,
|
|
||||||
module: &str,
|
|
||||||
annotations: Option<HashMap<String, String>>,
|
|
||||||
) {
|
|
||||||
info!(?reference, ?module, "pushing wasm module");
|
|
||||||
|
|
||||||
let data = async_std::fs::read(module)
|
|
||||||
.await
|
|
||||||
.expect("Cannot read Wasm module from disk");
|
|
||||||
|
|
||||||
let layers = vec![ImageLayer::new(
|
|
||||||
data,
|
|
||||||
manifest::WASM_LAYER_MEDIA_TYPE.to_string(),
|
|
||||||
None,
|
|
||||||
)];
|
|
||||||
|
|
||||||
let config = Config {
|
|
||||||
data: b"{}".to_vec(),
|
|
||||||
media_type: manifest::WASM_CONFIG_MEDIA_TYPE.to_string(),
|
|
||||||
annotations: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let image_manifest = manifest::OciImageManifest::build(&layers, &config, annotations);
|
|
||||||
|
|
||||||
let response = client
|
|
||||||
.push(reference, &layers, config, auth, Some(image_manifest))
|
|
||||||
.await
|
|
||||||
.map(|push_response| push_response.manifest_url)
|
|
||||||
.expect("Cannot push Wasm module");
|
|
||||||
|
|
||||||
println!("Wasm module successfully pushed {:?}", response);
|
|
||||||
}
|
|
||||||
|
|
@ -191,9 +191,11 @@ mod tests {
|
||||||
// Save current env vars
|
// Save current env vars
|
||||||
let old_config = env::var("DOCKER_CONFIG").ok();
|
let old_config = env::var("DOCKER_CONFIG").ok();
|
||||||
let old_path = env::var("PATH").ok();
|
let old_path = env::var("PATH").ok();
|
||||||
|
let old_registry_auth = env::var("REGISTRY_AUTH_FILE").ok();
|
||||||
|
|
||||||
// Set our temp dir in PATH and DOCKER_CONFIG
|
// Set our temp dir in PATH and DOCKER_CONFIG, clear REGISTRY_AUTH_FILE
|
||||||
env::set_var("DOCKER_CONFIG", tmp_dir.path());
|
env::set_var("DOCKER_CONFIG", tmp_dir.path());
|
||||||
|
env::remove_var("REGISTRY_AUTH_FILE");
|
||||||
let new_path = format!("{}:{}", tmp_dir.path().display(), env::var("PATH").unwrap_or_default());
|
let new_path = format!("{}:{}", tmp_dir.path().display(), env::var("PATH").unwrap_or_default());
|
||||||
env::set_var("PATH", new_path);
|
env::set_var("PATH", new_path);
|
||||||
|
|
||||||
|
|
@ -212,6 +214,11 @@ mod tests {
|
||||||
} else {
|
} else {
|
||||||
env::remove_var("PATH");
|
env::remove_var("PATH");
|
||||||
}
|
}
|
||||||
|
if let Some(val) = old_registry_auth {
|
||||||
|
env::set_var("REGISTRY_AUTH_FILE", val);
|
||||||
|
} else {
|
||||||
|
env::remove_var("REGISTRY_AUTH_FILE");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -278,18 +285,27 @@ mod tests {
|
||||||
|
|
||||||
fs::write(&auth_file, config).unwrap();
|
fs::write(&auth_file, config).unwrap();
|
||||||
|
|
||||||
// Save current env var
|
// Save current env vars
|
||||||
let old_val = env::var("REGISTRY_AUTH_FILE").ok();
|
let old_registry_auth = env::var("REGISTRY_AUTH_FILE").ok();
|
||||||
|
let old_docker_config = env::var("DOCKER_CONFIG").ok();
|
||||||
|
|
||||||
|
// Set REGISTRY_AUTH_FILE and clear DOCKER_CONFIG to avoid conflicts
|
||||||
env::set_var("REGISTRY_AUTH_FILE", auth_file.to_str().unwrap());
|
env::set_var("REGISTRY_AUTH_FILE", auth_file.to_str().unwrap());
|
||||||
|
env::remove_var("DOCKER_CONFIG");
|
||||||
|
|
||||||
let auth = resolve_docker_auth("special.registry.io/image").unwrap();
|
let auth = resolve_docker_auth("special.registry.io/image").unwrap();
|
||||||
assert_eq!(auth, RegistryAuth::Basic("authfile-user".to_string(), "authfile-pass".to_string()));
|
assert_eq!(auth, RegistryAuth::Basic("authfile-user".to_string(), "authfile-pass".to_string()));
|
||||||
|
|
||||||
// Restore env var
|
// Restore env vars
|
||||||
if let Some(val) = old_val {
|
if let Some(val) = old_registry_auth {
|
||||||
env::set_var("REGISTRY_AUTH_FILE", val);
|
env::set_var("REGISTRY_AUTH_FILE", val);
|
||||||
} else {
|
} else {
|
||||||
env::remove_var("REGISTRY_AUTH_FILE");
|
env::remove_var("REGISTRY_AUTH_FILE");
|
||||||
}
|
}
|
||||||
|
if let Some(val) = old_docker_config {
|
||||||
|
env::set_var("DOCKER_CONFIG", val);
|
||||||
|
} else {
|
||||||
|
env::remove_var("DOCKER_CONFIG");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
25
vendor/oci-distribution/src/secrets.rs
vendored
25
vendor/oci-distribution/src/secrets.rs
vendored
|
|
@ -1,5 +1,8 @@
|
||||||
//! Types for working with registry access secrets
|
//! Types for working with registry access secrets
|
||||||
|
|
||||||
|
use crate::errors::Result;
|
||||||
|
use crate::Reference;
|
||||||
|
|
||||||
/// A method for authenticating to a registry
|
/// A method for authenticating to a registry
|
||||||
#[derive(Eq, PartialEq, Debug, Clone)]
|
#[derive(Eq, PartialEq, Debug, Clone)]
|
||||||
pub enum RegistryAuth {
|
pub enum RegistryAuth {
|
||||||
|
|
@ -11,6 +14,28 @@ pub enum RegistryAuth {
|
||||||
Bearer(String),
|
Bearer(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl RegistryAuth {
|
||||||
|
/// Create a RegistryAuth by resolving from Docker config files and credential helpers
|
||||||
|
///
|
||||||
|
/// This will check:
|
||||||
|
/// 1. Docker config files (DOCKER_CONFIG, REGISTRY_AUTH_FILE, ~/.docker/config.json)
|
||||||
|
/// 2. Credential helpers specified in the config
|
||||||
|
/// 3. Default credential store
|
||||||
|
///
|
||||||
|
/// If no credentials are found, returns Anonymous auth.
|
||||||
|
pub fn from_default(image: &Reference) -> Result<Self> {
|
||||||
|
let image_str = image.whole();
|
||||||
|
crate::credential_helper::resolve_docker_auth(&image_str)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a RegistryAuth by resolving from Docker config files and credential helpers
|
||||||
|
///
|
||||||
|
/// This is similar to `from_default` but takes a string reference instead of a Reference.
|
||||||
|
pub fn from_default_str(image_ref: &str) -> Result<Self> {
|
||||||
|
crate::credential_helper::resolve_docker_auth(image_ref)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) trait Authenticable {
|
pub(crate) trait Authenticable {
|
||||||
fn apply_authentication(self, auth: &RegistryAuth) -> Self;
|
fn apply_authentication(self, auth: &RegistryAuth) -> Self;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue