- Introduced ExpandHosts function to parse and expand comma-separated host entries, including special values like "internal" and "localhost". - Updated gRPC server to utilize the new ExpandHosts function for improved host management. - Added HostHasInternal function to check for "internal" in host strings, enhancing configuration flexibility. - Implemented new gRPC endpoints for TaiTunnel registration and forwarding, improving tunnel communication capabilities. - Refactored authentication logic to include new TaiTunnel endpoints, ensuring proper access control. Made-with: Cursor
87 lines
2.3 KiB
Go
87 lines
2.3 KiB
Go
//go:build ci
|
|
|
|
package main
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
"github.com/yaoapp/yao/config"
|
|
"github.com/yaoapp/yao/engine"
|
|
"github.com/yaoapp/yao/openapi/oauth"
|
|
)
|
|
|
|
func main() {
|
|
appPath := flag.String("app", envOr("YAO_CI_APP_PATH", "."), "Yao application directory")
|
|
clientID := flag.String("client-id", envOr("YAO_CI_OAUTH_CLIENT_ID", "ci-tai"), "OAuth client ID embedded in token")
|
|
subject := flag.String("subject", envOr("YAO_CI_OAUTH_SUBJECT", "ci-tai"), "JWT subject claim")
|
|
scope := flag.String("scope", envOr("YAO_CI_OAUTH_SCOPE", "tai:tunnel"), "Token scope (space-separated)")
|
|
ttl := flag.String("ttl", envOr("YAO_CI_OAUTH_TTL", "24h"), "Token TTL (e.g. 1h, 24h, 168h)")
|
|
userID := flag.String("user-id", envOr("YAO_CI_OAUTH_USER_ID", ""), "User ID claim")
|
|
teamID := flag.String("team-id", envOr("YAO_CI_OAUTH_TEAM_ID", ""), "Team ID claim")
|
|
flag.Parse()
|
|
|
|
root, err := filepath.Abs(*appPath)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "ci-token: invalid app path: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
if err := os.Chdir(root); err != nil {
|
|
fmt.Fprintf(os.Stderr, "ci-token: chdir %s: %v\n", root, err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
config.Conf = config.LoadFrom(filepath.Join(root, ".env"))
|
|
config.Conf.Root = root
|
|
|
|
cfg := config.Conf
|
|
cfg.Session.IsCLI = true
|
|
|
|
warnings, err := engine.Load(cfg, engine.LoadOption{Action: "run"})
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "ci-token: engine.Load failed: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
for _, w := range warnings {
|
|
fmt.Fprintf(os.Stderr, "ci-token: warning [%s]: %v\n", w.Widget, w.Error)
|
|
}
|
|
|
|
if oauth.OAuth == nil {
|
|
fmt.Fprintln(os.Stderr, "ci-token: oauth service not initialized (openapi.Load may have failed)")
|
|
os.Exit(1)
|
|
}
|
|
|
|
dur, err := time.ParseDuration(*ttl)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "ci-token: invalid --ttl %q: %v\n", *ttl, err)
|
|
os.Exit(1)
|
|
}
|
|
expiresIn := int(dur.Seconds())
|
|
|
|
extraClaims := map[string]interface{}{}
|
|
if *userID != "" {
|
|
extraClaims["user_id"] = *userID
|
|
}
|
|
if *teamID != "" {
|
|
extraClaims["team_id"] = *teamID
|
|
}
|
|
|
|
token, err := oauth.OAuth.MakeAccessToken(*clientID, *scope, *subject, expiresIn, extraClaims)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "ci-token: MakeAccessToken failed: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
fmt.Print(token)
|
|
}
|
|
|
|
func envOr(key, fallback string) string {
|
|
if v := os.Getenv(key); v != "" {
|
|
return v
|
|
}
|
|
return fallback
|
|
}
|