Skip to content

Commit

Permalink
Merge pull request #19 from imjasonh/redirect-to-cgr-dev
Browse files Browse the repository at this point in the history
redirect distroless.dev/foo -> cgr.dev/chainguard/foo
  • Loading branch information
imjasonh authored Mar 23, 2023
2 parents 41e4cba + 75c91b0 commit 5230809
Show file tree
Hide file tree
Showing 12 changed files with 181 additions and 533 deletions.
58 changes: 3 additions & 55 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

This is a simple OCI redirector service that allows for custom domains, including forwarding auth token requests to the original registry.

For example, this is used to serve `distroless.dev/*` as a redirection to `ghcr.io/distroless/*`.
For example, this is used to serve `distroless.dev/*` as a redirection to `cgr.dev/chainguard/*`.

It's intended to be deployed to Google Cloud Run, which is responsible for handling HTTPS.
It's intended to be deployed to Google Cloud Run behind a GCLB load balancer, which is responsible for handling HTTPS.

## Deploying

Expand All @@ -26,56 +26,4 @@ $ terraform apply -var project=[MY-PROJECT]
url = "https://redirect-a1b2c3d4-uk.a.run.app"
```

This requires permission to push images to GCR, and to deploy Cloud Run services.

This will deploy to `us-east4` -- you can override with `-var region=[MY-REGION]`.

## Auth

To authorize through the redirection step (e.g., to access private images), you can configure credentials for the domain where the redirector is hosted.

This may be a Cloud Run service URL (something like `redirect-a1b2c3d4-uk.a.run.app`) or a mapped domain name.

When used this way, registry credentials are sent to the redirector, and are passed directly on to the real registry.
Credentials are never stored or logged by the redirector.

### GCR Auth

To configure auth to GCR, you can either:

- download a Service Account's JSON key as described in [GCR docs](https://cloud.google.com/container-registry/docs/advanced-authentication#json-key), or
- configure the [`docker-credential-gcr` cred helper](https://cloud.google.com/container-registry/docs/advanced-authentication#standalone-helper)

In either case, make sure to configure those creds _for the redirector's domain_, not `*.gcr.io`, e.g.:

```
cat keyfile.json | docker login redirect-a1b2c3d4-uk.a.run.app -u _json_key --password-stdin
```

or, in your `~/.docker/config.json`:

```
{
"credHelpers": {
"redirect-a1b2c3d4-uk.a.run.app": "gcr",
}
}
```

This will tell clients to use GCR creds to talk to the redirector, which will be passed through the redirector to GCR when you make requests.

### GHCR Auth

To configure auth to GHCR, you can use a personal access token as described in [GHCR docs](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry).

Make sure to configure those creds _for the redirector's domain_, not `ghcr.io`, e.g.:

```
echo $CR_PAT | docker login redirect-a1b2c3d4-uk.a.run.app -u USERNAME --password-stdin
```

This will tell clients to use GHCR creds to talk to the redirector, which will be passed through the redirector to GHCR when you make requests.

## Configuration

You can use this to host other redirections, to ghcr.io (the default) or gcr.io (using `--gcr=true`).
This requires permission to push images to GCR, and to deploy Cloud Run services and create GCP resources.
18 changes: 10 additions & 8 deletions e2e-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,21 @@ set -euxo pipefail
crane version >/dev/null \
|| { echo "install crane: https://github.com/google/go-containerregistry/blob/main/cmd/crane"; exit 1; }

# Kill whatever's running on :8080
# kill -9 $(lsof -ti:8080)

# Run the redirector in the background, kill it when the script exits.
go build && ./registry-redirect --prefix=unicorns &
go build && ./registry-redirect &
PID=$!
echo "server running with pid $PID"
trap 'kill $PID' EXIT

sleep 3 # Server isn't immediately ready.

crane digest localhost:8080/unicorns/nginx
crane manifest localhost:8080/unicorns/nginx
crane ls localhost:8080/unicorns/nginx

# TODO(jason): docker pull an image through the redirector.
crane digest localhost:8080/nginx
crane manifest localhost:8080/nginx
crane ls localhost:8080/nginx
crane pull localhost:8080/nginx /dev/null
crane validate --remote=localhost:8080/nginx

# TODO(jason): Run the redirector as a container connected to a kind cluster
# and pull through the redirector
echo PASSED
9 changes: 3 additions & 6 deletions env/jason-chainguard/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,7 @@ module "bq" {
module "gclb" {
source = "../../terraform/modules/gclb"

project = var.project
regions = var.regions
domains = [
"redirect.imjasonh.dev",
]
primary_domain = "redirect.imjasonh.dev"
project = var.project
regions = var.regions
domain = "redirect.imjasonh.dev"
}
10 changes: 3 additions & 7 deletions env/production/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,7 @@ module "bq" {
module "gclb" {
source = "../../terraform/modules/gclb"

project = var.project
regions = var.regions
domains = [
"cgr.dev",
"distroless.dev",
]
primary_domain = "cgr.dev"
project = var.project
regions = var.regions
domain = "distroless.dev"
}
31 changes: 1 addition & 30 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,40 +16,11 @@ import (
"knative.dev/pkg/logging"
)

// TODO:
// - Also support anonymous and Basic-type auth?
// - take a config for registries/repos to redirect from/to.

var (
// Redirect requests for distroless.dev/static -> ghcr.io/distroless/static
// If repo is empty, example.dev/foo/bar -> ghcr.io/foo/bar
repo = flag.String("repo", "distroless", "repo to redirect to")

// TODO(jason): Support arbitrary registries.
gcr = flag.Bool("gcr", false, "if true, use GCR mode")

// prefix is the user-visible repo prefix.
// For example, if repo is "distroless" and prefix is "unicorns",
// users hitting example.dev/unicorns/foo/bar will be redirected to
// ghcr.io/distroless/foo/bar.
// If prefix is unset, hitting example.dev/unicorns/foo/bar will
// redirect to ghcr.io/unicorns/foo/bar.
// If prefix is set, and users hit a path without the prefix, it's ignored:
// - example.dev/foo/bar -> ghcr.io/distroless/foo/bar
// (this is for backward compatibility with prefix-less redirects)
prefix = flag.String("prefix", "", "if set, user-visible repo prefix")
)

func main() {
flag.Parse()
logger := logging.FromContext(context.Background())

host := "ghcr.io"
if *gcr {
host = "gcr.io"
}
r := redirect.New(host, *repo, *prefix)
http.Handle("/", r)
http.Handle("/", redirect.New())

port := os.Getenv("PORT")
if port == "" {
Expand Down
Loading

0 comments on commit 5230809

Please sign in to comment.