Skip to content

Commit

Permalink
feat: sign.kontain.me
Browse files Browse the repository at this point in the history
Signed-off-by: Batuhan Apaydın <batuhan.apaydin@trendyol.com>
  • Loading branch information
developer-guy committed Nov 13, 2021
1 parent ed67da0 commit e5c39db
Show file tree
Hide file tree
Showing 6 changed files with 1,513 additions and 38 deletions.
15 changes: 15 additions & 0 deletions cmd/sign/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# `sign.kontain.me`

## Examples

Pull a mirrored [`busybox`](https://hub.docker.com/_/busybox) image:

```
docker pull sign.kontain.me/busybox
```

Or by tag:

```
docker pull sign.kontain.me/busybox:musl
```
14 changes: 14 additions & 0 deletions cmd/sign/deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/usr/bin/env bash

set -euxo pipefail

gcloud run deploy sign \
--project=kontaindotme \
--region=us-central1 \
--allow-unauthenticated \
--set-env-vars=BUCKET=kontaindotme \
--image=$(KO_DOCKER_REPO=gcr.io/kontaindotme ko publish -P ./cmd/sign) \
--memory=1Gi \
--cpu=1 \
--concurrency=80 \
--timeout=60 # 1m
124 changes: 124 additions & 0 deletions cmd/sign/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package main

import (
"context"
"fmt"
"log"
"net/http"
"os"
"strings"

"github.com/google/go-containerregistry/pkg/name"
"github.com/imjasonh/kontain.me/pkg/serve"

"github.com/sigstore/cosign/cmd/cosign/cli/options"
"github.com/sigstore/cosign/cmd/cosign/cli/sign"
fulcioclient "github.com/sigstore/fulcio/pkg/client"
)

func main() {
ctx := context.Background()
st, err := serve.NewStorage(ctx)
if err != nil {
log.Fatalf("serve.NewStorage: %v", err)
}
http.Handle("/v2/", &server{
info: log.New(os.Stdout, "I ", log.Ldate|log.Ltime|log.Lshortfile),
error: log.New(os.Stderr, "E ", log.Ldate|log.Ltime|log.Lshortfile),
storage: st,
})
http.Handle("/", http.RedirectHandler("https://github.com/imjasonh/kontain.me/blob/main/cmd/sign", http.StatusSeeOther))

log.Println("Starting...")
port := os.Getenv("PORT")
if port == "" {
port = "8080"
log.Printf("Defaulting to port %s", port)
}
log.Printf("Listening on port %s", port)
log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil))
}

type server struct {
info, error *log.Logger
storage *serve.Storage
}

func (s *server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
s.info.Println("handler:", r.Method, r.URL)
path := strings.TrimPrefix(r.URL.String(), "/v2/")

switch {
case path == "":
// API Version check.
w.Header().Set("Docker-Distribution-API-Version", "registry/2.0")
return
case strings.Contains(path, "/blobs/"),
strings.Contains(path, "/manifests/sha256:"):
// Extract requested blob digest and redirect to serve it from GCS.
// If it doesn't exist, this will return 404.
parts := strings.Split(r.URL.Path, "/")
digest := parts[len(parts)-1]
serve.Blob(w, r, digest)
case strings.Contains(path, "/manifests/"):
s.serveSignManifest(w, r)
default:
serve.Error(w, serve.ErrNotFound)
}
}

// sign.kontain.me/ubuntu -> mirror ubuntu and serve
func (s *server) serveSignManifest(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
path := strings.TrimPrefix(r.URL.Path, "/v2/")
parts := strings.Split(path, "/")

refstr := strings.Join(parts[:len(parts)-2], "/")
tagOrDigest := parts[len(parts)-1]
if strings.HasPrefix(tagOrDigest, "sha256:") {
refstr += "@" + tagOrDigest
} else {
refstr += ":" + tagOrDigest
}
for strings.HasPrefix(refstr, "sign.kontain.me/") {
refstr = strings.TrimPrefix(refstr, "sign.kontain.me/")
}

ref, err := name.ParseReference(refstr)
if err != nil {
s.error.Printf("ERROR (ParseReference(%q)): %v", refstr, err)
serve.Error(w, err)
return
}

// If it's a HEAD request, and request was by digest, and we have that
// manifest mirrored by digest already, serve HEAD response from GCS.
// If it's a HEAD request and the other conditions aren't met, we'll
// handle this later by consulting the real registry.
if r.Method == http.MethodHead {
if d, ok := ref.(name.Digest); ok {
if desc, err := s.storage.BlobExists(ctx, d.DigestStr()); err == nil {
w.Header().Set("Docker-Content-Digest", d.DigestStr())
w.Header().Set("Content-Type", string(desc.MediaType))
w.Header().Set("Content-Length", fmt.Sprintf("%d", desc.Size))
return
}
}
}

ko := sign.KeyOpts{
FulcioURL: fulcioclient.SigstorePublicServerURL,
RekorURL: "https://rekor.sigstore.dev",
OIDCIssuer: "https://oauth2.sigstore.dev/auth",
OIDCClientID: "sigstore",
}

fmt.Println("Image:", refstr)
err = sign.SignCmd(context.TODO(), ko, options.RegistryOptions{}, nil, []string{refstr}, "", true, "", false, false, "")

if err != nil {
s.error.Printf("ERROR (Cosign Keyless Sign(%q)): %v", refstr, err)
serve.Error(w, err)
return
}
}
6 changes: 6 additions & 0 deletions cmd/sign/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/usr/bin/env bash

set -euxo pipefail

time crane validate --remote=sign.kontain.me/busybox
time crane validate --remote=sign.kontain.me/busybox
21 changes: 9 additions & 12 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,23 @@ go 1.15

require (
cloud.google.com/go v0.97.0
cloud.google.com/go/storage v1.17.0
cloud.google.com/go/storage v1.18.2
github.com/containerd/stargz-snapshotter/estargz v0.9.0 // indirect
github.com/docker/cli v20.10.9+incompatible // indirect
github.com/docker/docker v20.10.9+incompatible // indirect
github.com/docker/docker-credential-helpers v0.6.4 // indirect
github.com/dustin/go-humanize v1.0.0
github.com/google/go-containerregistry v0.6.0
github.com/google/go-containerregistry v0.6.1-0.20210922191434-34b7f00d7a60
github.com/google/go-github/v32 v32.1.0
github.com/google/ko v0.9.3
github.com/imjasonh/delay v0.0.0-20210102151318-8339250e8458
github.com/sigstore/cosign v1.3.1
github.com/sigstore/fulcio v0.1.2-0.20210831152525-42f7422734bb
github.com/tmc/dot v0.0.0-20180926222610-6d252d5ff882
golang.org/x/mod v0.5.1
golang.org/x/net v0.0.0-20211007125505-59d4e928ea9d // indirect
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f
golang.org/x/oauth2 v0.0.0-20211028175245-ba495a64dcb5
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/tools v0.1.7 // indirect
google.golang.org/api v0.58.0
google.golang.org/genproto v0.0.0-20211005153810-c76a74d43a8e // indirect
google.golang.org/grpc v1.41.0 // indirect
google.golang.org/api v0.60.0
gopkg.in/yaml.v2 v2.4.0

)

replace k8s.io/client-go => k8s.io/client-go v0.22.3

0 comments on commit e5c39db

Please sign in to comment.