Skip to content

Commit

Permalink
Add insecure and plain-http flag when pull and push (oras-project#122)
Browse files Browse the repository at this point in the history
  • Loading branch information
pytimer authored and jdolitsky committed Oct 17, 2019
1 parent 205efe3 commit bbe4258
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 28 deletions.
20 changes: 15 additions & 5 deletions cmd/oras/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@ type pullOptions struct {
output string
verbose bool

debug bool
configs []string
username string
password string
debug bool
configs []string
username string
password string
insecure bool
plainHTTP bool
}

func pullCmd() *cobra.Command {
Expand All @@ -47,6 +49,12 @@ Example - Pull only files with the custom "application/vnd.me.hi" media type:
Example - Pull all files, any media type:
oras pull localhost:5000/hello:latest -a
Example - Pull files from the insecure registry:
oras pull localhost:5000/hello:latest --insecure
Example - Pull files from the HTTP registry:
oras pull localhost:5000/hello:latest --plain-http
`,
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
Expand All @@ -66,6 +74,8 @@ Example - Pull all files, any media type:
cmd.Flags().StringArrayVarP(&opts.configs, "config", "c", nil, "auth config path")
cmd.Flags().StringVarP(&opts.username, "username", "u", "", "registry username")
cmd.Flags().StringVarP(&opts.password, "password", "p", "", "registry password")
cmd.Flags().BoolVarP(&opts.insecure, "insecure", "", false, "allow connections to SSL registry without certs")
cmd.Flags().BoolVarP(&opts.plainHTTP, "plain-http", "", false, "use plain http and not https")
return cmd
}

Expand All @@ -82,7 +92,7 @@ func runPull(opts pullOptions) error {
opts.allowedMediaTypes = []string{content.DefaultBlobMediaType, content.DefaultBlobDirMediaType}
}

resolver := newResolver(opts.username, opts.password, opts.configs...)
resolver := newResolver(opts.username, opts.password, opts.insecure, opts.plainHTTP, opts.configs...)
store := content.NewFileStore(opts.output)
defer store.Close()
store.DisableOverwrite = opts.keepOldFiles
Expand Down
20 changes: 15 additions & 5 deletions cmd/oras/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,12 @@ type pushOptions struct {
pathValidationDisabled bool
verbose bool

debug bool
configs []string
username string
password string
debug bool
configs []string
username string
password string
insecure bool
plainHTTP bool
}

func pushCmd() *cobra.Command {
Expand All @@ -55,6 +57,12 @@ Example - Push multiple files with different media types:
Example - Push file "hi.txt" with the custom manifest config "config.json" of the custom "application/vnd.me.config" media type:
oras push --manifest-config config.json:application/vnd.me.config localhost:5000/hello:latest hi.txt
Example - Push file to the insecure registry:
oras push localhost:5000/hello:latest hi.txt --insecure
Example - Push file to the HTTP registry:
oras push localhost:5000/hello:latest hi.txt --plain-http
`,
Args: cobra.MinimumNArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
Expand All @@ -72,6 +80,8 @@ Example - Push file "hi.txt" with the custom manifest config "config.json" of th
cmd.Flags().StringArrayVarP(&opts.configs, "config", "c", nil, "auth config path")
cmd.Flags().StringVarP(&opts.username, "username", "u", "", "registry username")
cmd.Flags().StringVarP(&opts.password, "password", "p", "", "registry password")
cmd.Flags().BoolVarP(&opts.insecure, "insecure", "", false, "allow connections to SSL registry without certs")
cmd.Flags().BoolVarP(&opts.plainHTTP, "plain-http", "", false, "use plain http and not https")
return cmd
}

Expand Down Expand Up @@ -119,7 +129,7 @@ func runPush(opts pushOptions) error {
}

// ready to push
resolver := newResolver(opts.username, opts.password, opts.configs...)
resolver := newResolver(opts.username, opts.password, opts.insecure, opts.plainHTTP, opts.configs...)
pushOpts = append(pushOpts, oras.WithPushBaseHandler(pushStatusTrack()))
desc, err := oras.Push(ctx, resolver, opts.targetRef, store, files, pushOpts...)
if err != nil {
Expand Down
33 changes: 25 additions & 8 deletions cmd/oras/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package main

import (
"context"
"crypto/tls"
"fmt"
"net/http"
"os"

auth "github.com/deislabs/oras/pkg/auth/docker"
Expand All @@ -11,22 +13,37 @@ import (
"github.com/containerd/containerd/remotes/docker"
)

func newResolver(username, password string, configs ...string) remotes.Resolver {
if username != "" || password != "" {
return docker.NewResolver(docker.ResolverOptions{
Credentials: func(hostName string) (string, string, error) {
return username, password, nil
func newResolver(username, password string, insecure bool, plainHTTP bool, configs ...string) remotes.Resolver {

opts := docker.ResolverOptions{
PlainHTTP: plainHTTP,
}

client := http.DefaultClient
if insecure {
client.Transport = &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
})
}
}
opts.Client = client


if username != "" || password != "" {
opts.Credentials = func(hostName string) (string, string, error) {
return username, password, nil
}
return docker.NewResolver(opts)
}
cli, err := auth.NewClient(configs...)
if err != nil {
fmt.Fprintf(os.Stderr, "WARNING: Error loading auth file: %v\n", err)
}
resolver, err := cli.Resolver(context.Background())
resolver, err := cli.Resolver(context.Background(), client, plainHTTP)
if err != nil {
fmt.Fprintf(os.Stderr, "WARNING: Error loading resolver: %v\n", err)
resolver = docker.NewResolver(docker.ResolverOptions{})
resolver = docker.NewResolver(opts)
}
return resolver
}
92 changes: 84 additions & 8 deletions implementors.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,30 +73,106 @@ To login to the registry without a certificate, a self-signed certificate, or an
```sh
htpasswd -cB -b auth.htpasswd myuser mypass
```

- Generate your self-signed certificates:

```sh
$ mkdir -p certs
$ openssl req \
-newkey rsa:4096 -nodes -sha256 -keyout certs/domain.key \
-x509 -days 365 -out certs/domain.crt
```

- Start a registry using that file for auth and listen the `0.0.0.0` address:

```sh
docker run -it --rm -p 8443:443 \
docker run -it --rm -p 5000:5000 \
-v `pwd`/certs:/certs \
-v $(pwd)/auth.htpasswd:/etc/docker/registry/auth.htpasswd \
-e REGISTRY_AUTH="{htpasswd: {realm: localhost, path: /etc/docker/registry/auth.htpasswd}}" \
-e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
-e REGISTRY_HTTP_ADDR=0.0.0.0:5000 \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
registry
```

- In a new window, login with `oras` using the ip address not localhost:

```sh
oras login -u myuser -p mypass --insecure <registry-ip>:8443
oras login -u myuser -p mypass --insecure <registry-ip>:5000
```

You will notice a new entry for `<registry-ip>:8443` appear in `~/.docker/config.json`.
You will notice a new entry for `<registry-ip>:5000` appear in `~/.docker/config.json`.

To remove the entry from the credentials file, use `oras logout`:
Then you can pull files from the registry or push files to the registry.

```sh
oras logout <registry-ip>:8443
```
- To push single file to this registry:

```sh
oras push <registry-ip>:5000/library/hello:latest hi.txt --insecure
```

- To pull files from this registry:

```sh
oras pull <registry-ip>:5000/library/hello:latest --insecure
```

- To remove the entry from the credentials file, use `oras logout`:

```sh
oras logout <registry-ip>:5000
```

#### Using an plain HTTP Docker registry

To pull or push the HTTP Docker registry. `oras` support `--plain-http` flag to pull or push.

The `--plain-http` flag mean that you want to use http instead of https to connect the Docker registry.

- Create a valid htpasswd file (must use `-B` for bcrypt):

```sh
htpasswd -cB -b auth.htpasswd myuser mypass
```

- Start a registry using that file for auth and listen the `0.0.0.0` address:

```sh
docker run -it --rm -p 5000:5000 \
-v $(pwd)/auth.htpasswd:/etc/docker/registry/auth.htpasswd \
-e REGISTRY_AUTH="{htpasswd: {realm: localhost, path: /etc/docker/registry/auth.htpasswd}}" \
-e REGISTRY_HTTP_ADDR=0.0.0.0:5000 \
registry
```

- In a new window, login with `oras` using the ip address not localhost:

```sh
oras login -u myuser -p mypass --insecure <registry-ip>:5000
```

You will notice a new entry for `<registry-ip>:5000` appear in `~/.docker/config.json`.

Then you can pull files from the registry or push files to the registry.

- To push single file to this registry:

```sh
oras push <registry-ip>:5000/library/hello:latest hi.txt --plain-http
```

- To pull files from this registry:

```sh
oras pull <registry-ip>:5000/library/hello:latest --plain-http
```

- To remove the entry from the credentials file, use `oras logout`:

```sh
oras logout <registry-ip>:5000
```

### [Azure Container Registry (ACR)](https://aka.ms/acr)

Expand Down
3 changes: 2 additions & 1 deletion pkg/auth/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package auth
import (
"context"
"errors"
"net/http"

"github.com/containerd/containerd/remotes"
)
Expand All @@ -19,5 +20,5 @@ type Client interface {
// Logout logs out from a remote server identified by the hostname.
Logout(ctx context.Context, hostname string) error
// Resolver returns a new authenticated resolver.
Resolver(ctx context.Context) (remotes.Resolver, error)
Resolver(ctx context.Context, client *http.Client, plainHTTP bool) (remotes.Resolver, error)
}
5 changes: 4 additions & 1 deletion pkg/auth/docker/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package docker

import (
"context"
"net/http"

"github.com/containerd/containerd/remotes"
"github.com/containerd/containerd/remotes/docker"
Expand All @@ -10,9 +11,11 @@ import (
)

// Resolver returns a new authenticated resolver.
func (c *Client) Resolver(_ context.Context) (remotes.Resolver, error) {
func (c *Client) Resolver(_ context.Context, client *http.Client, plainHTTP bool) (remotes.Resolver, error) {
return docker.NewResolver(docker.ResolverOptions{
Credentials: c.Credential,
Client: client,
PlainHTTP: plainHTTP,
}), nil
}

Expand Down

0 comments on commit bbe4258

Please sign in to comment.