Compare commits

..

2 Commits

Author SHA1 Message Date
Jeff McCune
4184619afc (#126) Refactor pkg to internal
pkg folder is not needed.  Move everything internal for now.
2024-04-12 13:56:16 -07:00
Jeff McCune
954dbd1ec8 (#126) Refactor id token acquisition to token package
And add a logout command that deletes the token cache.

The token package is intended for subcommands that need to make API
calls to the holos api server, getting a token should be a simple matter
of calling the token.Get() method, which takes minimal dependencies.
2024-04-12 13:15:03 -07:00
76 changed files with 271 additions and 175 deletions

View File

@@ -4,7 +4,7 @@ PROJ=holos
ORG_PATH=github.com/holos-run
REPO_PATH=$(ORG_PATH)/$(PROJ)
VERSION := $(shell cat pkg/version/embedded/major pkg/version/embedded/minor pkg/version/embedded/patch | xargs printf "%s.%s.%s")
VERSION := $(shell cat version/embedded/major version/embedded/minor version/embedded/patch | xargs printf "%s.%s.%s")
BIN_NAME := holos
DOCKER_REPO=quay.io/openinfrastructure/holos
@@ -19,7 +19,7 @@ GIT_COMMIT=$(shell git rev-parse HEAD)
GIT_TREE_STATE=$(shell test -n "`git status --porcelain`" && echo "dirty" || echo "clean")
BUILD_DATE=$(shell date -Iseconds)
LD_FLAGS="-w -X ${ORG_PATH}/${PROJ}/pkg/version.GitCommit=${GIT_COMMIT} -X ${ORG_PATH}/${PROJ}/pkg/version.GitTreeState=${GIT_TREE_STATE} -X ${ORG_PATH}/${PROJ}/pkg/version.BuildDate=${BUILD_DATE}"
LD_FLAGS="-w -X ${ORG_PATH}/${PROJ}/version.GitCommit=${GIT_COMMIT} -X ${ORG_PATH}/${PROJ}/version.GitTreeState=${GIT_TREE_STATE} -X ${ORG_PATH}/${PROJ}/version.BuildDate=${BUILD_DATE}"
.PHONY: default
default: test

View File

@@ -8,9 +8,9 @@ import (
"strings"
"github.com/holos-run/holos"
"github.com/holos-run/holos/pkg/errors"
"github.com/holos-run/holos/pkg/logger"
"github.com/holos-run/holos/pkg/util"
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/internal/logger"
"github.com/holos-run/holos/internal/util"
)
// A HelmChart represents a helm command to provide chart values in order to render kubernetes api objects.

View File

@@ -4,9 +4,9 @@ import (
"context"
"github.com/holos-run/holos"
"github.com/holos-run/holos/pkg/errors"
"github.com/holos-run/holos/pkg/logger"
"github.com/holos-run/holos/pkg/util"
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/internal/logger"
"github.com/holos-run/holos/internal/util"
)
const KustomizeBuildKind = "KustomizeBuild"

View File

@@ -7,9 +7,9 @@ import (
"path/filepath"
"slices"
"github.com/holos-run/holos/pkg/errors"
"github.com/holos-run/holos/pkg/logger"
"github.com/holos-run/holos/pkg/util"
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/internal/logger"
"github.com/holos-run/holos/internal/util"
)
// Result is the build result for display or writing. Holos components Render the Result as a data pipeline.

View File

@@ -1,8 +1,9 @@
package main
import (
"github.com/holos-run/holos/pkg/cli"
"os"
"github.com/holos-run/holos/internal/cli"
)
func main() {

View File

@@ -1,10 +1,11 @@
package main
import (
"github.com/holos-run/holos/pkg/cli"
"github.com/rogpeppe/go-internal/testscript"
"os"
"testing"
"github.com/holos-run/holos/internal/cli"
"github.com/rogpeppe/go-internal/testscript"
)
func TestMain(m *testing.M) {

View File

@@ -4,10 +4,10 @@ import (
"fmt"
"strings"
"github.com/holos-run/holos/pkg/cli/command"
"github.com/holos-run/holos/pkg/errors"
"github.com/holos-run/holos/pkg/holos"
"github.com/holos-run/holos/pkg/internal/builder"
"github.com/holos-run/holos/internal/cli/command"
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/internal/holos"
"github.com/holos-run/holos/internal/internal/builder"
"github.com/spf13/cobra"
)

View File

@@ -3,8 +3,8 @@ package command
import (
"fmt"
"github.com/holos-run/holos/pkg/errors"
"github.com/holos-run/holos/pkg/version"
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/version"
"github.com/spf13/cobra"
)
@@ -26,5 +26,6 @@ func New(name string) *cobra.Command {
SilenceUsage: true,
SilenceErrors: true,
}
cmd.Flags().SortFlags = false
return cmd
}

View File

@@ -1,9 +1,9 @@
package create
import (
"github.com/holos-run/holos/pkg/cli/command"
"github.com/holos-run/holos/pkg/cli/secret"
"github.com/holos-run/holos/pkg/holos"
"github.com/holos-run/holos/internal/cli/command"
"github.com/holos-run/holos/internal/cli/secret"
"github.com/holos-run/holos/internal/holos"
"github.com/spf13/cobra"
)

View File

@@ -1,9 +1,9 @@
package get
import (
"github.com/holos-run/holos/pkg/cli/command"
"github.com/holos-run/holos/pkg/cli/secret"
"github.com/holos-run/holos/pkg/holos"
"github.com/holos-run/holos/internal/cli/command"
"github.com/holos-run/holos/internal/cli/secret"
"github.com/holos-run/holos/internal/holos"
"github.com/spf13/cobra"
)

View File

@@ -5,12 +5,12 @@ import (
"fmt"
"sort"
"github.com/holos-run/holos/pkg/cli/command"
"github.com/holos-run/holos/pkg/cli/secret"
"github.com/holos-run/holos/pkg/errors"
"github.com/holos-run/holos/pkg/holos"
"github.com/holos-run/holos/pkg/logger"
"github.com/holos-run/holos/pkg/util"
"github.com/holos-run/holos/internal/cli/command"
"github.com/holos-run/holos/internal/cli/secret"
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/internal/holos"
"github.com/holos-run/holos/internal/logger"
"github.com/holos-run/holos/internal/util"
"github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

View File

@@ -1,9 +1,9 @@
package kv
import (
"github.com/holos-run/holos/pkg/cli/command"
"github.com/holos-run/holos/pkg/errors"
"github.com/holos-run/holos/pkg/holos"
"github.com/holos-run/holos/internal/cli/command"
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/internal/holos"
"github.com/spf13/cobra"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"

View File

@@ -1,10 +1,10 @@
package kv
import (
"github.com/holos-run/holos/pkg/cli/command"
"github.com/holos-run/holos/pkg/cli/secret"
"github.com/holos-run/holos/pkg/errors"
"github.com/holos-run/holos/pkg/holos"
"github.com/holos-run/holos/internal/cli/command"
"github.com/holos-run/holos/internal/cli/secret"
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/internal/holos"
"github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

View File

@@ -11,11 +11,11 @@ import (
"path/filepath"
"strings"
"github.com/holos-run/holos/pkg/cli/command"
"github.com/holos-run/holos/pkg/cli/secret"
"github.com/holos-run/holos/pkg/errors"
"github.com/holos-run/holos/pkg/holos"
"github.com/holos-run/holos/pkg/logger"
"github.com/holos-run/holos/internal/cli/command"
"github.com/holos-run/holos/internal/cli/secret"
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/internal/holos"
"github.com/holos-run/holos/internal/logger"
"github.com/spf13/cobra"
"golang.org/x/tools/txtar"
v1 "k8s.io/api/core/v1"

View File

@@ -0,0 +1,47 @@
package login
import (
"context"
"flag"
"fmt"
"log/slog"
"github.com/holos-run/holos/internal/cli/command"
"github.com/holos-run/holos/internal/holos"
"github.com/holos-run/holos/internal/token"
"github.com/spf13/cobra"
)
// New returns a new login command.
func New(cfg *holos.Config) *cobra.Command {
cmd := command.New("login")
var printClaims bool
config := token.NewConfig()
cmd.Flags().AddGoFlagSet(config.FlagSet())
fs := &flag.FlagSet{}
fs.BoolVar(&printClaims, "print-claims", false, "print id token claims")
cmd.Flags().AddGoFlagSet(fs)
cmd.RunE = func(c *cobra.Command, args []string) error {
ctx := c.Context()
if ctx == nil {
ctx = context.Background()
}
token, err := token.Get(ctx, cfg.Logger(), config)
if err != nil {
slog.Error("could not get token", "err", err)
return fmt.Errorf("could not get token: %w", err)
}
claims := token.Claims()
slog.Info("logged in as "+claims.Email, "name", claims.Name, "exp", token.Expiry, "email", claims.Email)
if printClaims {
fmt.Fprintln(cmd.OutOrStdout(), token.Pretty)
}
return nil
}
return cmd
}

View File

@@ -0,0 +1,24 @@
package logout
import (
"fmt"
"os"
"github.com/holos-run/holos/internal/cli/command"
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/internal/holos"
"github.com/holos-run/holos/internal/token"
"github.com/spf13/cobra"
)
func New(cfg *holos.Config) *cobra.Command {
cmd := command.New("logout")
cmd.RunE = func(c *cobra.Command, args []string) error {
if err := os.RemoveAll(token.CacheDir); err != nil {
return errors.Wrap(fmt.Errorf("could not logout: %w", err))
}
cfg.Logger().Info("logged out: removed " + token.CacheDir)
return nil
}
return cmd
}

View File

@@ -6,8 +6,8 @@ import (
"log/slog"
cue "cuelang.org/go/cue/errors"
"github.com/holos-run/holos/pkg/errors"
"github.com/holos-run/holos/pkg/holos"
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/internal/holos"
)
// MakeMain makes a main function for the cli or tests.

View File

@@ -5,9 +5,9 @@ import (
"fmt"
"strings"
"github.com/holos-run/holos/pkg/errors"
"github.com/holos-run/holos/pkg/logger"
"github.com/holos-run/holos/pkg/util"
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/internal/logger"
"github.com/holos-run/holos/internal/util"
)
type ghAuthStatusResponse string

View File

@@ -5,9 +5,9 @@ import (
"github.com/spf13/cobra"
"github.com/holos-run/holos/pkg/cli/command"
"github.com/holos-run/holos/pkg/holos"
"github.com/holos-run/holos/pkg/logger"
"github.com/holos-run/holos/internal/cli/command"
"github.com/holos-run/holos/internal/holos"
"github.com/holos-run/holos/internal/logger"
)
// Config holds configuration parameters for preflight checks.

View File

@@ -3,11 +3,11 @@ package render
import (
"fmt"
"github.com/holos-run/holos/pkg/cli/command"
"github.com/holos-run/holos/pkg/errors"
"github.com/holos-run/holos/pkg/holos"
"github.com/holos-run/holos/pkg/internal/builder"
"github.com/holos-run/holos/pkg/logger"
"github.com/holos-run/holos/internal/cli/command"
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/internal/holos"
"github.com/holos-run/holos/internal/internal/builder"
"github.com/holos-run/holos/internal/logger"
"github.com/spf13/cobra"
)

View File

@@ -7,17 +7,18 @@ import (
"github.com/holos-run/holos/internal/server"
"github.com/holos-run/holos/pkg/cli/build"
"github.com/holos-run/holos/pkg/cli/create"
"github.com/holos-run/holos/pkg/cli/get"
"github.com/holos-run/holos/pkg/cli/kv"
"github.com/holos-run/holos/pkg/cli/login"
"github.com/holos-run/holos/pkg/cli/preflight"
"github.com/holos-run/holos/pkg/cli/render"
"github.com/holos-run/holos/pkg/cli/txtar"
"github.com/holos-run/holos/pkg/holos"
"github.com/holos-run/holos/pkg/logger"
"github.com/holos-run/holos/pkg/version"
"github.com/holos-run/holos/internal/cli/build"
"github.com/holos-run/holos/internal/cli/create"
"github.com/holos-run/holos/internal/cli/get"
"github.com/holos-run/holos/internal/cli/kv"
"github.com/holos-run/holos/internal/cli/login"
"github.com/holos-run/holos/internal/cli/logout"
"github.com/holos-run/holos/internal/cli/preflight"
"github.com/holos-run/holos/internal/cli/render"
"github.com/holos-run/holos/internal/cli/txtar"
"github.com/holos-run/holos/internal/holos"
"github.com/holos-run/holos/internal/logger"
"github.com/holos-run/holos/version"
)
// New returns a new root *cobra.Command for command line execution.
@@ -58,6 +59,7 @@ func New(cfg *holos.Config) *cobra.Command {
rootCmd.AddCommand(create.New(cfg))
rootCmd.AddCommand(preflight.New(cfg))
rootCmd.AddCommand(login.New(cfg))
rootCmd.AddCommand(logout.New(cfg))
// Maybe not needed?
rootCmd.AddCommand(txtar.New(cfg))

View File

@@ -2,12 +2,13 @@ package cli
import (
"bytes"
"github.com/holos-run/holos/pkg/holos"
"github.com/holos-run/holos/pkg/logger"
"github.com/holos-run/holos/pkg/version"
"github.com/spf13/cobra"
"strings"
"testing"
"github.com/holos-run/holos/internal/holos"
"github.com/holos-run/holos/internal/logger"
"github.com/holos-run/holos/version"
"github.com/spf13/cobra"
)
func newCommand() (*cobra.Command, *bytes.Buffer) {

View File

@@ -9,10 +9,10 @@ import (
"path/filepath"
"strings"
"github.com/holos-run/holos/pkg/cli/command"
"github.com/holos-run/holos/pkg/errors"
"github.com/holos-run/holos/pkg/holos"
"github.com/holos-run/holos/pkg/logger"
"github.com/holos-run/holos/internal/cli/command"
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/internal/holos"
"github.com/holos-run/holos/internal/logger"
"github.com/spf13/cobra"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

View File

@@ -8,11 +8,11 @@ import (
"path/filepath"
"sort"
"github.com/holos-run/holos/pkg/cli/command"
"github.com/holos-run/holos/pkg/errors"
"github.com/holos-run/holos/pkg/holos"
"github.com/holos-run/holos/pkg/logger"
"github.com/holos-run/holos/pkg/util"
"github.com/holos-run/holos/internal/cli/command"
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/internal/holos"
"github.com/holos-run/holos/internal/logger"
"github.com/holos-run/holos/internal/util"
"github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

View File

@@ -1,7 +1,7 @@
package secret
import (
"github.com/holos-run/holos/pkg/holos"
"github.com/holos-run/holos/internal/holos"
"github.com/spf13/pflag"
)

View File

@@ -1,15 +1,16 @@
package secret_test
import (
"github.com/holos-run/holos/pkg/cli"
"github.com/holos-run/holos/pkg/holos"
"testing"
"time"
"github.com/holos-run/holos/internal/cli"
"github.com/holos-run/holos/internal/holos"
"github.com/rogpeppe/go-internal/testscript"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/fake"
"testing"
"time"
)
const clientsetKey = "clientset"

View File

@@ -8,10 +8,10 @@ import (
"os"
"path/filepath"
"github.com/holos-run/holos/pkg/cli/command"
"github.com/holos-run/holos/pkg/errors"
"github.com/holos-run/holos/pkg/holos"
"github.com/holos-run/holos/pkg/util"
"github.com/holos-run/holos/internal/cli/command"
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/internal/holos"
"github.com/holos-run/holos/internal/util"
"github.com/spf13/cobra"
"golang.org/x/tools/txtar"
)

View File

@@ -9,7 +9,7 @@ import (
"strings"
"testing"
"github.com/holos-run/holos/pkg/errors"
"github.com/holos-run/holos/internal/errors"
)
const prefix = "errors_test.go:"

View File

@@ -9,8 +9,8 @@ import (
"path/filepath"
"strings"
"github.com/holos-run/holos/pkg/errors"
"github.com/holos-run/holos/pkg/logger"
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/internal/logger"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/util/homedir"

View File

@@ -17,8 +17,8 @@ import (
"github.com/holos-run/holos/api/v1alpha1"
"github.com/holos-run/holos"
"github.com/holos-run/holos/pkg/errors"
"github.com/holos-run/holos/pkg/logger"
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/internal/logger"
)
const (

View File

@@ -13,9 +13,9 @@ import (
"strings"
"time"
"github.com/holos-run/holos/pkg/errors"
"github.com/holos-run/holos/pkg/tint"
"github.com/holos-run/holos/pkg/version"
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/internal/tint"
"github.com/holos-run/holos/version"
"github.com/mattn/go-isatty"
"github.com/spf13/cobra"
)

View File

@@ -10,12 +10,12 @@ import (
"github.com/sethvargo/go-retry"
"github.com/spf13/cobra"
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/internal/holos"
"github.com/holos-run/holos/internal/server/db"
"github.com/holos-run/holos/internal/server/middleware/authn"
"github.com/holos-run/holos/internal/server/server"
"github.com/holos-run/holos/internal/server/signals"
"github.com/holos-run/holos/pkg/errors"
"github.com/holos-run/holos/pkg/holos"
)
//go:embed help/root.txt

View File

@@ -8,8 +8,8 @@ import (
"entgo.io/ent/dialect"
"github.com/holos-run/holos/internal/ent"
"github.com/holos-run/holos/pkg/errors"
"github.com/holos-run/holos/pkg/holos"
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/internal/holos"
)
// Conn holds database connection info

View File

@@ -7,8 +7,8 @@ import (
"entgo.io/ent/dialect"
entsql "entgo.io/ent/dialect/sql"
"github.com/holos-run/holos/internal/ent"
"github.com/holos-run/holos/pkg/errors"
"github.com/holos-run/holos/pkg/holos"
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/internal/holos"
_ "github.com/jackc/pgx/v5/stdlib"
)

View File

@@ -8,8 +8,8 @@ import (
esql "entgo.io/ent/dialect/sql"
"github.com/holos-run/holos/internal/ent"
"github.com/holos-run/holos/pkg/errors"
"github.com/holos-run/holos/pkg/holos"
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/internal/holos"
"modernc.org/sqlite"
)

View File

@@ -4,8 +4,8 @@ import (
"context"
"testing"
"github.com/holos-run/holos/internal/holos"
"github.com/holos-run/holos/internal/server/testutils"
"github.com/holos-run/holos/pkg/holos"
"github.com/stretchr/testify/assert"
)

View File

@@ -5,8 +5,8 @@ import (
"connectrpc.com/connect"
"github.com/holos-run/holos/internal/ent"
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/internal/server/middleware/authn"
"github.com/holos-run/holos/pkg/errors"
holos "github.com/holos-run/holos/service/gen/holos/v1alpha1"
"google.golang.org/protobuf/types/known/timestamppb"
)

View File

@@ -6,9 +6,9 @@ import (
"connectrpc.com/connect"
"github.com/holos-run/holos/internal/ent"
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/internal/server/middleware/authn"
"github.com/holos-run/holos/internal/server/middleware/logger"
"github.com/holos-run/holos/pkg/errors"
holos "github.com/holos-run/holos/service/gen/holos/v1alpha1"
)

View File

@@ -11,8 +11,8 @@ import (
"time"
"github.com/coreos/go-oidc/v3/oidc"
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/internal/server/middleware/logger"
"github.com/holos-run/holos/pkg/errors"
)
// Verifier is the interface that wraps the basic Verify method to verify an

View File

@@ -9,7 +9,7 @@ import (
"strings"
"time"
"github.com/holos-run/holos/pkg/logger"
"github.com/holos-run/holos/internal/logger"
)
func NewContext(ctx context.Context, log *slog.Logger) context.Context {

View File

@@ -10,12 +10,12 @@ import (
"connectrpc.com/connect"
"connectrpc.com/validate"
"github.com/holos-run/holos/internal/ent"
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/internal/frontend"
"github.com/holos-run/holos/internal/holos"
"github.com/holos-run/holos/internal/server/handler"
"github.com/holos-run/holos/internal/server/middleware/authn"
"github.com/holos-run/holos/internal/server/middleware/logger"
"github.com/holos-run/holos/pkg/errors"
"github.com/holos-run/holos/pkg/holos"
"github.com/holos-run/holos/service/gen/holos/v1alpha1/holosconnect"
"github.com/prometheus/client_golang/prometheus/promhttp"
"golang.org/x/net/http2"

View File

@@ -10,10 +10,10 @@ import (
"github.com/coreos/go-oidc/v3/oidc"
"github.com/holos-run/holos/internal/ent"
"github.com/holos-run/holos/internal/frontend"
"github.com/holos-run/holos/internal/holos"
"github.com/holos-run/holos/internal/server/db"
"github.com/holos-run/holos/internal/server/server"
"github.com/holos-run/holos/internal/server/testutils"
"github.com/holos-run/holos/pkg/holos"
"github.com/stretchr/testify/assert"
)

View File

@@ -1,7 +1,9 @@
package login
// Package token obtains, caches, and provides an ID token to authenticate to the holos api server.
package token
import (
"context"
"encoding/json"
"flag"
"fmt"
"log/slog"
@@ -9,9 +11,7 @@ import (
"strings"
"time"
"github.com/holos-run/holos/pkg/cli/command"
"github.com/holos-run/holos/pkg/errors"
"github.com/holos-run/holos/pkg/holos"
"github.com/holos-run/holos/internal/errors"
"github.com/int128/kubelogin/pkg/infrastructure/browser"
"github.com/int128/kubelogin/pkg/infrastructure/clock"
"github.com/int128/kubelogin/pkg/infrastructure/logger"
@@ -25,54 +25,11 @@ import (
"github.com/int128/kubelogin/pkg/usecases/authentication/authcode"
"github.com/int128/kubelogin/pkg/usecases/authentication/devicecode"
"github.com/int128/kubelogin/pkg/usecases/authentication/ropc"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"k8s.io/client-go/util/homedir"
)
type Config struct {
Issuer string
ClientID string
Scopes string
PrintClaims bool
ForceRefresh bool
}
// New returns a new login command.
func New(cfg *holos.Config) *cobra.Command {
cmd := command.New("login")
config := Config{}
flags := flag.NewFlagSet("", flag.ContinueOnError)
flags.StringVar(&config.Issuer, "issuer", "https://login.ois.run", "id token issuer.")
flags.StringVar(&config.ClientID, "client-id", "262479925313799528@holos_platform", "oidc client id.")
flags.StringVar(&config.Scopes, "scopes", "openid email profile groups offline_access urn:zitadel:iam:org:domain:primary:openinfrastructure.co", "oidc scopes")
flags.BoolVar(&config.ForceRefresh, "force-refresh", false, "force refresh")
flags.BoolVar(&config.PrintClaims, "print-claims", false, "print id token claims")
cmd.Flags().SortFlags = false
cmd.Flags().AddGoFlagSet(flags)
cmd.RunE = func(c *cobra.Command, args []string) error {
ctx := c.Context()
if ctx == nil {
ctx = context.Background()
}
// TODO Plumb the client ID and scopes as flags.
token, err := GetToken(ctx, cfg.Logger(), config)
if err != nil {
slog.Error("could not get token", "err", err)
return fmt.Errorf("could not get token: %w", err)
}
slog.Info("have id token", "exp", token.Expiry)
if config.PrintClaims {
fmt.Fprintln(cmd.OutOrStdout(), token.Pretty)
}
return nil
}
return cmd
}
var CacheDir = expandHomedir(filepath.Join("~", ".holos", "cache"))
// Token represents an authorization bearer token. Token is useful as an output
// dto of the Tokener service use case.
@@ -83,15 +40,65 @@ type Token struct {
Expiry time.Time
// Pretty is the JSON encoding of the token claims
Pretty string
// claims represent decoded claims
claims *Claims
}
// GetToken returns an oidc token for use as an authorization bearer http header.
func GetToken(ctx context.Context, log *slog.Logger, cfg Config) (*Token, error) {
func (t Token) Claims() *Claims {
if t.claims == nil {
json.Unmarshal([]byte(t.Pretty), &t.claims)
}
return t.claims
}
type Claims struct {
Email string `json:"email"`
Name string `json:"name"`
}
// NewConfig returns a Config with default values.
func NewConfig() Config {
return Config{
Issuer: "https://login.ois.run",
ClientID: "262479925313799528@holos_platform",
Scopes: []string{"openid", "email", "profile", "groups", "offline_access"},
ExtraScopes: []string{"urn:zitadel:iam:org:domain:primary:openinfrastructure.co"},
}
}
type Config struct {
Issuer string
ClientID string
Scopes stringSlice
ExtraScopes stringSlice
ForceRefresh bool
flagSet *flag.FlagSet
}
func (c *Config) FlagSet() *flag.FlagSet {
if c.flagSet != nil {
return c.flagSet
}
flags := flag.NewFlagSet("", flag.ContinueOnError)
flags.StringVar(&c.Issuer, "oidc-issuer", c.Issuer, "oidc token issuer url.")
flags.StringVar(&c.ClientID, "oidc-client-id", c.ClientID, "oidc client id.")
flags.Var(&c.Scopes, "oidc-scopes", "required oidc scopes")
flags.Var(&c.ExtraScopes, "oidc-extra-scopes", "optional oidc scopes")
flags.BoolVar(&c.ForceRefresh, "oidc-force-refresh", c.ForceRefresh, "force refresh")
c.flagSet = flags
return flags
}
// Get returns an oidc token for use as an authorization bearer http header.
func Get(ctx context.Context, log *slog.Logger, cfg Config) (*Token, error) {
var scopes []string
scopes = append(scopes, cfg.Scopes...)
scopes = append(scopes, cfg.ExtraScopes...)
provider := oidc.Provider{
IssuerURL: cfg.Issuer,
ClientID: cfg.ClientID,
UsePKCE: true,
ExtraScopes: strings.Split(cfg.Scopes, " "),
ExtraScopes: scopes,
}
authenticationOptions := authenticationOptions{
@@ -125,7 +132,7 @@ func GetToken(ctx context.Context, log *slog.Logger, cfg Config) (*Token, error)
tokenCacheRepository := &repository.Repository{}
cachedTokenSet, err := tokenCacheRepository.FindByKey(defaultTokenCacheDir, tokenCacheKey)
cachedTokenSet, err := tokenCacheRepository.FindByKey(CacheDir, tokenCacheKey)
if err != nil {
slog.Debug("could not find a token cache (continuing)", "err", err, "handled", true)
}
@@ -172,7 +179,7 @@ func GetToken(ctx context.Context, log *slog.Logger, cfg Config) (*Token, error)
slog.Debug("existing token valid", "refreshed", 0, "exp", idTokenClaims.Expiry)
} else {
slog.Debug("new token valid", "refreshed", 1, "exp", idTokenClaims.Expiry)
if err := tokenCacheRepository.Save(defaultTokenCacheDir, tokenCacheKey, authenticationOutput.TokenSet); err != nil {
if err := tokenCacheRepository.Save(CacheDir, tokenCacheKey, authenticationOutput.TokenSet); err != nil {
slog.Debug("could not save token cache", "err", err, "handled", 0)
return nil, fmt.Errorf("could not save token cache: %w", err)
}
@@ -187,8 +194,6 @@ func GetToken(ctx context.Context, log *slog.Logger, cfg Config) (*Token, error)
}
var defaultListenAddress = []string{"127.0.0.1:8000", "127.0.0.1:18000"}
var defaultTokenCacheDir = expandHomedir(filepath.Join("~", ".holos", "cache"))
var allGrantType = strings.Join([]string{
"auto",
"authcode",
@@ -275,3 +280,15 @@ func (l *holosLogger) V(level int) logger.Verbose {
func (*holosLogger) IsEnabled(level int) bool {
return true
}
// stringSlice is a comma separated list of string values
type stringSlice []string
func (s *stringSlice) String() string {
return strings.Join((*s)[:], ",")
}
func (s *stringSlice) Set(value string) error {
*s = append(*s, strings.Split(value, ",")...)
return nil
}

View File

@@ -2,8 +2,9 @@ package util
import (
"context"
"github.com/holos-run/holos/pkg/logger"
"os"
"github.com/holos-run/holos/internal/logger"
)
// Remove cleans up path, useful for temporary directories.

View File

@@ -6,7 +6,7 @@ import (
"os"
"os/exec"
"github.com/holos-run/holos/pkg/logger"
"github.com/holos-run/holos/internal/logger"
)
// runResult holds the stdout and stderr of a command.

View File

@@ -4,7 +4,7 @@ import (
"io/fs"
"os"
"github.com/holos-run/holos/pkg/errors"
"github.com/holos-run/holos/internal/errors"
"golang.org/x/tools/txtar"
)

View File

@@ -1 +0,0 @@
0

View File

@@ -1,4 +1,4 @@
#! /bin/bash
VERSION=${2:-$(( $(<pkg/version/embedded/${1:-patch}) + 1 ))}
echo $VERSION > pkg/version/embedded/${1:-patch}
VERSION=${2:-$(( $(<version/embedded/${1:-patch}) + 1 ))}
echo $VERSION > version/embedded/${1:-patch}

1
version/embedded/patch Normal file
View File

@@ -0,0 +1 @@
2