Skip to content

Commit 1d06a97

Browse files
rgarciasjmiller609
andauthored
gen jwt script (#4)
* Export images to rootfs with docker * docker client dependency injection * Fix permissions during extraction * Don't skip docker in tests * extraction test passing but seems too complicated * Use umoci for image to rootfs conversion * Update docs * Update README * Move OCI cache dir * Tweak disk settings * Async API * Simplify async API: remove sse for now * Avoid rate limit in CI * Add API level image test * Check queuing works * Test failure on invalid tag * Fix image filesystem layout * image name validation * Update README * Clean up error * Use erofs * API layer depends on domain cmd/api/api (handlers) ↓ depends on lib/images, lib/instances, lib/volumes (domain) ↓ independent of lib/oapi (API types) * Idempotency and race conditions * Add erofs to ci * OCI client internal to image manager * Disambiguate digests and tags * WIP: figuring out error handling registry errors * Switch to more lightweight library for interacting with registry * Handle 404 * Use docker auth config file * Add timeout on resolve * Update README * Poll by digest * Tweak readme * caching test * More comprehensive basic test * gen jwt script * fix merge --------- Co-authored-by: Steven Miller <[email protected]>
1 parent 65a64a5 commit 1d06a97

File tree

7 files changed

+67
-11
lines changed

7 files changed

+67
-11
lines changed

.env.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
JWT_SECRET='your-secret-key-here'
2+
DATA_DIR=/home/your-user/hypeman/.datadir # or leave unset to default to /var/lib/hypeman

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ bin/**
1313
.env
1414
tmp
1515
tmp/**
16+
.datadir

Makefile

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
SHELL := /bin/bash
2-
.PHONY: oapi-generate generate-wire generate-all dev build test install-tools
2+
.PHONY: oapi-generate generate-wire generate-all dev build test install-tools gen-jwt
33

44
# Directory where local binaries will be installed
55
BIN_DIR ?= $(CURDIR)/bin
@@ -11,6 +11,7 @@ $(BIN_DIR):
1111
OAPI_CODEGEN ?= $(BIN_DIR)/oapi-codegen
1212
AIR ?= $(BIN_DIR)/air
1313
WIRE ?= $(BIN_DIR)/wire
14+
GODOTENV ?= $(BIN_DIR)/godotenv
1415

1516
# Install oapi-codegen
1617
$(OAPI_CODEGEN): | $(BIN_DIR)
@@ -24,7 +25,11 @@ $(AIR): | $(BIN_DIR)
2425
$(WIRE): | $(BIN_DIR)
2526
GOBIN=$(BIN_DIR) go install github.com/google/wire/cmd/wire@latest
2627

27-
install-tools: $(OAPI_CODEGEN) $(AIR) $(WIRE)
28+
# Install godotenv for loading .env files
29+
$(GODOTENV): | $(BIN_DIR)
30+
GOBIN=$(BIN_DIR) go install github.com/joho/godotenv/cmd/godotenv@latest
31+
32+
install-tools: $(OAPI_CODEGEN) $(AIR) $(WIRE) $(GODOTENV)
2833

2934
# Generate Go code from OpenAPI spec
3035
oapi-generate: $(OAPI_CODEGEN)
@@ -53,6 +58,11 @@ dev: $(AIR)
5358
test:
5459
go test -tags containers_image_openpgp -v -timeout 30s ./...
5560

61+
# Generate JWT token for testing
62+
# Usage: make gen-jwt [USER_ID=test-user]
63+
gen-jwt: $(GODOTENV)
64+
@$(GODOTENV) -f .env go run ./cmd/gen-jwt -user-id $${USER_ID:-test-user}
65+
5666
# Clean generated files and binaries
5767
clean:
5868
rm -rf $(BIN_DIR)

README.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,18 @@ make build
4949
```
5050
### Running the Server
5151

52-
Start the server with hot-reload for development:
52+
1. Copy the example environment file and modify the values:
53+
```bash
54+
cp .env.example .env
55+
# Edit .env and set JWT_SECRET and other configuration values
56+
```
57+
58+
2. Generate a JWT token for testing (optional):
59+
```bash
60+
make gen-jwt
61+
```
62+
63+
3. Start the server with hot-reload for development:
5364
```bash
5465
make dev
5566
```

cmd/api/api/images.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ func (s *ApiService) ListImages(ctx context.Context, request oapi.ListImagesRequ
2020
Message: "failed to list images",
2121
}, nil
2222
}
23-
23+
2424
oapiImages := make([]oapi.Image, len(domainImages))
2525
for i, img := range domainImages {
2626
oapiImages[i] = imageToOAPI(img)
2727
}
28-
28+
2929
return oapi.ListImages200JSONResponse(oapiImages), nil
3030
}
3131

cmd/gen-jwt/main.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package main
2+
3+
import (
4+
"flag"
5+
"fmt"
6+
"os"
7+
"time"
8+
9+
"github.com/golang-jwt/jwt/v5"
10+
)
11+
12+
func main() {
13+
jwtSecret := os.Getenv("JWT_SECRET")
14+
if jwtSecret == "" {
15+
fmt.Fprintf(os.Stderr, "Error: JWT_SECRET environment variable is not set\n")
16+
os.Exit(1)
17+
}
18+
userID := flag.String("user-id", "test-user", "User ID to include in the JWT token")
19+
flag.Parse()
20+
21+
claims := jwt.MapClaims{
22+
"sub": *userID,
23+
"iat": time.Now().Unix(),
24+
"exp": time.Now().Add(24 * time.Hour).Unix(),
25+
}
26+
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
27+
tokenString, err := token.SignedString([]byte(jwtSecret))
28+
if err != nil {
29+
fmt.Fprintf(os.Stderr, "Error generating token: %v\n", err)
30+
os.Exit(1)
31+
}
32+
33+
fmt.Println(tokenString)
34+
}

lib/images/oci.go

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
"github.com/google/go-containerregistry/pkg/v1/empty"
1212
"github.com/google/go-containerregistry/pkg/v1/layout"
1313
"github.com/google/go-containerregistry/pkg/v1/remote"
14-
"github.com/opencontainers/image-spec/specs-go/v1"
14+
v1 "github.com/opencontainers/image-spec/specs-go/v1"
1515
rspec "github.com/opencontainers/runtime-spec/specs-go"
1616
"github.com/opencontainers/umoci/oci/cas/dir"
1717
"github.com/opencontainers/umoci/oci/casext"
@@ -70,7 +70,7 @@ func (c *ociClient) inspectManifest(ctx context.Context, imageRef string) (strin
7070

7171
// Use system authentication (reads from ~/.docker/config.json, etc.)
7272
// Default retry: only on network errors, max ~1.3s total
73-
descriptor, err := remote.Head(ref,
73+
descriptor, err := remote.Head(ref,
7474
remote.WithContext(ctx),
7575
remote.WithAuthFromKeychain(authn.DefaultKeychain))
7676
if err != nil {
@@ -126,7 +126,7 @@ func (c *ociClient) pullToOCILayout(ctx context.Context, imageRef, layoutTag str
126126

127127
// Use system authentication (reads from ~/.docker/config.json, etc.)
128128
// Default retry: only on network errors, max ~1.3s total
129-
img, err := remote.Image(ref,
129+
img, err := remote.Image(ref,
130130
remote.WithContext(ctx),
131131
remote.WithAuthFromKeychain(authn.DefaultKeychain))
132132
if err != nil {
@@ -293,7 +293,7 @@ func (c *ociClient) unpackLayers(ctx context.Context, imageRef, targetDir string
293293
// Map container UIDs to current user's UID (identity mapping)
294294
uid := uint32(os.Getuid())
295295
gid := uint32(os.Getgid())
296-
296+
297297
unpackOpts := &layer.UnpackOptions{
298298
OnDiskFormat: layer.DirRootfs{
299299
MapOptions: layer.MapOptions{
@@ -307,7 +307,7 @@ func (c *ociClient) unpackLayers(ctx context.Context, imageRef, targetDir string
307307
},
308308
},
309309
}
310-
310+
311311
err = layer.UnpackRootfs(context.Background(), casEngine, targetDir, manifest, unpackOpts)
312312
if err != nil {
313313
return fmt.Errorf("unpack rootfs: %w", err)
@@ -322,4 +322,3 @@ type containerMetadata struct {
322322
Env map[string]string
323323
WorkingDir string
324324
}
325-

0 commit comments

Comments
 (0)