Skip to content

Commit e7cc9d6

Browse files
committed
feat: add ability to login to private registries
1 parent f16ebe2 commit e7cc9d6

File tree

2 files changed

+53
-2
lines changed

2 files changed

+53
-2
lines changed

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,19 @@ Another example, for copying only the manifests directory:
7979
$ dcp quay.io/tflannag/bundles:resolveset-v0.0.2 -c manifests
8080
```
8181

82+
Lastly, we can reference a private registry by providing a username
83+
and password (specified via the `-u` and `-p` flags).
84+
85+
```
86+
$ dcp quay.io/tyslaton/sample-catalog-private:latest -u <username> -p <password>
87+
```
88+
89+
**Note**: This serves as a convenient way to connect to private
90+
registries but is insecure locally as your credentials are saved in
91+
your shell's history. If you would like to remain completely secure then
92+
login via `<container_runtime> login` and pull the image locally. `dcp`
93+
will then be able to notice the image locally pulled and process it.
94+
8295
## Testing
8396

8497
If you would like to run the test suite, you just need to run the standard cargo command. This will run all relevant

src/lib.rs

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
use anyhow::{anyhow, Result};
22
use clap::{App, Arg};
3-
use docker_api::api::{ContainerCreateOpts, PullOpts, RmContainerOpts};
3+
use docker_api::api::{ContainerCreateOpts, PullOpts, RegistryAuth, RmContainerOpts};
44
use futures_util::{StreamExt, TryStreamExt};
55
use podman_api::opts::ContainerCreateOpts as PodmanContainerCreateOpts;
66
use podman_api::opts::PullOpts as PodmanPullOpts;
7+
use podman_api::opts::RegistryAuth as PodmanRegistryAuth;
78
use std::path::PathBuf;
89
use tar::Archive;
910

@@ -28,6 +29,10 @@ pub struct Config {
2829
write_to_stdout: bool,
2930
// What level of logs to output
3031
log_level: String,
32+
// Username for singing into a private registry
33+
username: String,
34+
// Password for signing into a private registry
35+
password: String,
3136
}
3237

3338
pub fn get_args() -> Result<Config> {
@@ -65,6 +70,24 @@ pub fn get_args() -> Result<Config> {
6570
.short("w")
6671
.long("write-to-stdout"),
6772
)
73+
.arg(
74+
Arg::with_name("username")
75+
.value_name("USERNAME")
76+
.help("Username used for singing into a private registry.")
77+
.short("u")
78+
.long("username")
79+
.default_value(""),
80+
81+
)
82+
.arg(
83+
Arg::with_name("password")
84+
.value_name("PASSWORD")
85+
.help("Password used for signing into a private registry. * WARNING *: Writing credentials to your terminal is risky. Be sure you are okay with them showing up in your history")
86+
.short("p")
87+
.long("password")
88+
.default_value(""),
89+
90+
)
6891
.arg(
6992
Arg::with_name("log-level")
7093
.value_name("LOG-LEVEL")
@@ -80,6 +103,9 @@ pub fn get_args() -> Result<Config> {
80103
let content_path = matches.value_of("content-path").unwrap().to_string();
81104
let write_to_stdout = matches.is_present("write-to-stdout");
82105
let log_level = matches.value_of("log-level").unwrap().to_string();
106+
// TODO (tyslaton): Need to come up with a way for this to be extracted from the docker config to be more secure locally.
107+
let username = matches.value_of("username").unwrap().to_string();
108+
let password = matches.value_of("password").unwrap().to_string();
83109

84110
if write_to_stdout {
85111
return Err(anyhow!(
@@ -93,6 +119,8 @@ pub fn get_args() -> Result<Config> {
93119
content_path,
94120
write_to_stdout,
95121
log_level,
122+
username,
123+
password,
96124
})
97125
}
98126

@@ -132,7 +160,12 @@ pub async fn run(config: Config) -> Result<()> {
132160
};
133161

134162
if let Some(docker) = &rt.docker {
135-
let pull_opts = PullOpts::builder().image(repo).tag(tag).build();
163+
let auth = RegistryAuth::builder()
164+
.username(config.username)
165+
.password(config.password)
166+
.build();
167+
let pull_opts = PullOpts::builder().image(repo).tag(tag).auth(auth).build();
168+
136169
let images = docker.images();
137170
let mut stream = images.pull(&pull_opts);
138171

@@ -147,8 +180,13 @@ pub async fn run(config: Config) -> Result<()> {
147180
}
148181
}
149182
} else {
183+
let auth = PodmanRegistryAuth::builder()
184+
.username(config.username)
185+
.password(config.password)
186+
.build();
150187
let pull_opts = PodmanPullOpts::builder()
151188
.reference(config.image.clone().trim())
189+
.auth(auth)
152190
.build();
153191
let images = rt.podman.as_ref().unwrap().images();
154192
let mut stream = images.pull(&pull_opts);

0 commit comments

Comments
 (0)