Skip to content

Commit

Permalink
Merge pull request #366 from Kuadrant/cmd-line-args
Browse files Browse the repository at this point in the history
CLI
  • Loading branch information
guicassolato authored Nov 30, 2022
2 parents 90dd08f + bff3d02 commit 3ba0baa
Show file tree
Hide file tree
Showing 7 changed files with 197 additions and 115 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ WORKDIR /
COPY --from=builder /workspace/authorino .
USER 1001

ENTRYPOINT ["/authorino"]
ENTRYPOINT ["/authorino", "server"]
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ manifests: controller-gen kustomize ## Generates the manifests in $PROJECT_DIR/i
controller-gen crd:crdVersions=v1 rbac:roleName=manager-role webhook paths="./..." output:crd:artifacts:config=install/crd output:rbac:artifacts:config=install/rbac && kustomize build install > $(AUTHORINO_MANIFESTS)

run: generate manifests ## Runs the application against the Kubernetes cluster configured in ~/.kube/config
go run -ldflags "-X main.version=$(VERSION)" ./main.go
go run -ldflags "-X main.version=$(VERSION)" ./main.go server

build: generate ## Builds the manager binary
CGO_ENABLED=0 GO111MODULE=on go build -a -ldflags "-X main.version=$(VERSION)" -o bin/authorino main.go
Expand Down
4 changes: 3 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ require (
github.com/hashicorp/go-multierror v1.1.1
github.com/open-policy-agent/opa v0.43.1
github.com/prometheus/client_golang v1.12.2
github.com/spf13/cobra v1.5.0
github.com/spf13/pflag v1.0.5
github.com/tidwall/gjson v1.14.0
go.uber.org/zap v1.19.1
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd
Expand Down Expand Up @@ -59,6 +61,7 @@ require (
github.com/googleapis/gnostic v0.5.5 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
Expand All @@ -72,7 +75,6 @@ require (
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect
github.com/sirupsen/logrus v1.9.0 // indirect
github.com/spf13/cast v1.4.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
github.com/vektah/gqlparser/v2 v2.4.6 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -681,6 +681,7 @@ github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/intel/goresctrl v0.2.0/go.mod h1:+CZdzouYFn5EsxgqAQTEzMfwKwuc0fVdMrT9FCCAVRQ=
Expand Down Expand Up @@ -1030,6 +1031,7 @@ github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHN
github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk=
github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=
github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU=
github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
Expand Down
221 changes: 109 additions & 112 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,13 @@ import (
"crypto/sha256"
"crypto/tls"
"encoding/hex"
"flag"
"fmt"
"net"
"net/http"
"os"
"strconv"
"time"

envoy_auth "github.com/envoyproxy/go-control-plane/envoy/service/auth/v3"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
healthpb "google.golang.org/grpc/health/grpc_health_v1"

grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"

"github.com/go-logr/logr"
api "github.com/kuadrant/authorino/api/v1beta1"
"github.com/kuadrant/authorino/controllers"
"github.com/kuadrant/authorino/pkg/evaluators"
Expand All @@ -44,7 +35,16 @@ import (
"github.com/kuadrant/authorino/pkg/log"
"github.com/kuadrant/authorino/pkg/metrics"
"github.com/kuadrant/authorino/pkg/service"
"github.com/kuadrant/authorino/pkg/utils"

envoy_auth "github.com/envoyproxy/go-control-plane/envoy/service/auth/v3"
grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
healthpb "google.golang.org/grpc/health/grpc_health_v1"
"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
Expand All @@ -55,119 +55,108 @@ import (
)

const (
envWatchNamespace = "WATCH_NAMESPACE"
envWatchedAuthConfigLabelSelector = "AUTH_CONFIG_LABEL_SELECTOR"
envWatchedSecretLabelSelector = "SECRET_LABEL_SELECTOR"
envLogLevel = "LOG_LEVEL"
envLogMode = "LOG_MODE"
envTimeout = "TIMEOUT"
envExtAuthGRPCPort = "EXT_AUTH_GRPC_PORT"
envExtAuthHTTPPort = "EXT_AUTH_HTTP_PORT"
envTLSCertPath = "TLS_CERT"
envTLSCertKeyPath = "TLS_CERT_KEY"
envOIDCHTTPPort = "OIDC_HTTP_PORT"
envOIDCTLSCertPath = "OIDC_TLS_CERT"
envOIDCTLSCertKeyPath = "OIDC_TLS_CERT_KEY"
envEvaluatorCacheSize = "EVALUATOR_CACHE_SIZE" // in megabytes
envDeepMetricsEnabled = "DEEP_METRICS_ENABLED"
envMaxHttpRequestBodySize = "MAX_HTTP_REQUEST_BODY_SIZE" // in bytes

flagMetricsAddr = "metrics-addr"
flagHealthProbeAddr = "health-probe-addr"
flagEnableLeaderElection = "enable-leader-election"

defaultWatchNamespace = ""
defaultWatchedAuthConfigLabelSelector = ""
defaultWatchedSecretLabelSelector = "authorino.kuadrant.io/managed-by=authorino"
defaultLogLevel = "info"
defaultLogMode = "production"
defaultTimeout = "0"
defaultExtAuthGRPCPort = "50051"
defaultExtAuthHTTPPort = "5001"
defaultTLSCertPath = ""
defaultTLSCertKeyPath = ""
defaultOIDCHTTPPort = "8083"
defaultOIDCTLSCertPath = ""
defaultOIDCTLSCertKeyPath = ""
defaultEvaluatorCacheSize = "1"
defaultDeepMetricsEnabled = "false"
defaultMetricsAddr = ":8080"
defaultHealthProbeAddr = ":8081"
defaultEnableLeaderElection = false
defaultMaxHttpRequestBodySize = "8192" // 8KB

gRPCMaxConcurrentStreams = 10000
leaderElectionIDSuffix = "authorino.kuadrant.io"
)

var (
watchNamespace = fetchEnv(envWatchNamespace, defaultWatchNamespace)
watchedAuthConfigLabelSelector = fetchEnv(envWatchedAuthConfigLabelSelector, defaultWatchedAuthConfigLabelSelector)
watchedSecretLabelSelector = fetchEnv(envWatchedSecretLabelSelector, defaultWatchedSecretLabelSelector)
logLevel = fetchEnv(envLogLevel, defaultLogLevel)
logMode = fetchEnv(envLogMode, defaultLogMode)
timeout, _ = strconv.Atoi(fetchEnv(envTimeout, defaultTimeout))
timeoutMs = time.Duration(timeout) * time.Millisecond
extAuthGRPCPort = fetchEnv(envExtAuthGRPCPort, defaultExtAuthGRPCPort)
extAuthHTTPPort = fetchEnv(envExtAuthHTTPPort, defaultExtAuthHTTPPort)
tlsCertPath = fetchEnv(envTLSCertPath, defaultTLSCertPath)
tlsCertKeyPath = fetchEnv(envTLSCertKeyPath, defaultTLSCertKeyPath)
oidcHTTPPort = fetchEnv(envOIDCHTTPPort, defaultOIDCHTTPPort)
oidcTLSCertPath = fetchEnv(envOIDCTLSCertPath, defaultOIDCTLSCertPath)
oidcTLSCertKeyPath = fetchEnv(envOIDCTLSCertKeyPath, defaultOIDCTLSCertKeyPath)
metadataCacheSize = fetchEnv(envEvaluatorCacheSize, defaultEvaluatorCacheSize)
deepMetricEnabled = fetchEnv(envDeepMetricsEnabled, defaultDeepMetricsEnabled)
maxHttpRequestBodySize, _ = strconv.ParseInt(fetchEnv(envMaxHttpRequestBodySize, defaultMaxHttpRequestBodySize), 10, 64)

scheme = runtime.NewScheme()
logOpts = log.Options{Level: log.ToLogLevel(logLevel), Mode: log.ToLogMode(logMode)}
logger = log.NewLogger(logOpts).WithName("authorino")

// ldflags
version string

// option flags
watchNamespace string
watchedAuthConfigLabelSelector string
watchedSecretLabelSelector string
logLevel string
logMode string
timeout int
extAuthGRPCPort int
extAuthHTTPPort int
tlsCertPath string
tlsCertKeyPath string
oidcHTTPPort int
oidcTLSCertPath string
oidcTLSCertKeyPath string
evaluatorCacheSize int
deepMetricsEnabled bool
metricsAddr string
healthProbeAddr string
enableLeaderElection bool
maxHttpRequestBodySize int64

scheme = runtime.NewScheme()

logger logr.Logger
)

func init() {
utilruntime.Must(clientgoscheme.AddToScheme(scheme))

utilruntime.Must(api.AddToScheme(scheme))
// +kubebuilder:scaffold:scheme
}

log.SetLogger(logger, logOpts)
func main() {
cmdRoot := &cobra.Command{
Use: "authorino",
Short: "Authorino is a Kubernetes-native authorization server.",
}

cmdServer := &cobra.Command{
Use: "server",
Short: "Runs the authorization server",
Run: run,
}

evaluators.EvaluatorCacheSize, _ = strconv.Atoi(metadataCacheSize)
metrics.DeepMetricsEnabled, _ = strconv.ParseBool(deepMetricEnabled)
cmdServer.PersistentFlags().StringVar(&watchNamespace, "watch-namespace", utils.EnvVar("WATCH_NAMESPACE", ""), "Kubernetes namespace to watch")
cmdServer.PersistentFlags().StringVar(&watchedAuthConfigLabelSelector, "auth-config-label-selector", utils.EnvVar("AUTH_CONFIG_LABEL_SELECTOR", ""), "Kubernetes label selector to filter AuthConfig resources to watch")
cmdServer.PersistentFlags().StringVar(&watchedSecretLabelSelector, "secret-label-selector", utils.EnvVar("SECRET_LABEL_SELECTOR", "authorino.kuadrant.io/managed-by=authorino"), "Kubernetes label selector to filter Secret resources to watch")
cmdServer.PersistentFlags().StringVar(&logLevel, "log-level", utils.EnvVar("LOG_LEVEL", "info"), "Log level")
cmdServer.PersistentFlags().StringVar(&logMode, "log-mode", utils.EnvVar("LOG_MODE", "production"), "Log mode")
cmdServer.PersistentFlags().IntVar(&timeout, "timeout", utils.EnvVar("TIMEOUT", 0), "Server timeout - in milliseconds")
cmdServer.PersistentFlags().IntVar(&extAuthGRPCPort, "ext-auth-grpc-port", utils.EnvVar("EXT_AUTH_GRPC_PORT", 50051), "Port number of authorization server - gRPC interface")
cmdServer.PersistentFlags().IntVar(&extAuthHTTPPort, "ext-auth-http-port", utils.EnvVar("EXT_AUTH_HTTP_PORT", 5001), "Port number of authorization server - raw HTTP interface")
cmdServer.PersistentFlags().StringVar(&tlsCertPath, "tls-cert", utils.EnvVar("TLS_CERT", ""), "Path to the public TLS server certificate file in the file system - authorization server")
cmdServer.PersistentFlags().StringVar(&tlsCertKeyPath, "tls-cert-key", utils.EnvVar("TLS_CERT_KEY", ""), "Path to the private TLS server certificate key file in the file system - authorization server")
cmdServer.PersistentFlags().IntVar(&oidcHTTPPort, "oidc-http-port", utils.EnvVar("OIDC_HTTP_PORT", 8083), "Port number of OIDC Discovery server for Festival Wristband tokens")
cmdServer.PersistentFlags().StringVar(&oidcTLSCertPath, "oidc-tls-cert", utils.EnvVar("OIDC_TLS_CERT", ""), "Path to the public TLS server certificate file in the file system - Festival Wristband OIDC Discovery server")
cmdServer.PersistentFlags().StringVar(&oidcTLSCertKeyPath, "oidc-tls-cert-key", utils.EnvVar("OIDC_TLS_CERT_KEY", ""), "Path to the private TLS server certificate key file in the file system - Festival Wristband OIDC Discovery server")
cmdServer.PersistentFlags().IntVar(&evaluatorCacheSize, "evaluator-cache-size", utils.EnvVar("EVALUATOR_CACHE_SIZE", 1), "Cache size of each Authorino evaluator if enabled in the AuthConfig - in megabytes")
cmdServer.PersistentFlags().BoolVar(&deepMetricsEnabled, "deep-metrics-enabled", utils.EnvVar("DEEP_METRICS_ENABLED", false), "Enable deep metrics at the level of each evaluator when requested in the AuthConfig, exported by the metrics server")
cmdServer.PersistentFlags().StringVar(&metricsAddr, "metrics-addr", ":8080", "The network address the metrics endpoint binds to")
cmdServer.PersistentFlags().StringVar(&healthProbeAddr, "health-probe-addr", ":8081", "The network address the health probe endpoint binds to")
cmdServer.PersistentFlags().BoolVar(&enableLeaderElection, "enable-leader-election", false, "Enable leader election for status updater - ensures only one instance of Authorino tries to update the status of reconciled resources")
cmdServer.PersistentFlags().Int64Var(&maxHttpRequestBodySize, "max-http-request-body-size", utils.EnvVar("MAX_HTTP_REQUEST_BODY_SIZE", int64(8192)), "Maximum size of the body of requests accepted in the raw HTTP interface of the authorization server - in bytes")

cmdVersion := &cobra.Command{
Use: "version",
Short: "Prints the Authorino version info",
Run: printVersion,
}

cmdRoot.AddCommand(cmdServer, cmdVersion)

if err := cmdRoot.Execute(); err != nil {
fmt.Println("error: ", err)
os.Exit(1)
}
}

func main() {
var metricsAddr, healthProbeAddr string
var enableLeaderElection bool
flag.StringVar(&metricsAddr, flagMetricsAddr, defaultMetricsAddr, "The address the metric endpoint binds to.")
flag.StringVar(&healthProbeAddr, flagHealthProbeAddr, defaultHealthProbeAddr, "The address the health probe endpoint binds to.")
flag.BoolVar(&enableLeaderElection, flagEnableLeaderElection, defaultEnableLeaderElection, "Enable leader election for status updater. Ensures only one instance of Authorino tries to update the status of reconciled resources.")
flag.Parse()
func run(cmd *cobra.Command, _ []string) {
logOpts := log.Options{Level: log.ToLogLevel(logLevel), Mode: log.ToLogMode(logMode)}
logger = log.NewLogger(logOpts).WithName("authorino")
log.SetLogger(logger, logOpts)

logger.Info("booting up authorino", "version", version)

logger.V(1).Info("setting up with options",
envWatchNamespace, watchNamespace,
envWatchedAuthConfigLabelSelector, watchedAuthConfigLabelSelector,
envWatchedSecretLabelSelector, watchedSecretLabelSelector,
envLogLevel, logLevel,
envLogMode, logMode,
envTimeout, timeout,
envExtAuthGRPCPort, extAuthGRPCPort,
envExtAuthHTTPPort, extAuthHTTPPort,
envTLSCertPath, tlsCertPath,
envTLSCertKeyPath, tlsCertKeyPath,
envOIDCHTTPPort, oidcHTTPPort,
envOIDCTLSCertPath, oidcTLSCertPath,
envOIDCTLSCertKeyPath, oidcTLSCertKeyPath,
envEvaluatorCacheSize, metadataCacheSize,
envDeepMetricsEnabled, deepMetricEnabled,
flagMetricsAddr, metricsAddr,
flagHealthProbeAddr, healthProbeAddr,
flagEnableLeaderElection, enableLeaderElection,
)
var flags []interface{}
cmd.PersistentFlags().VisitAll(func(flag *pflag.Flag) {
flags = append(flags, flag.Name, flag.Value.String())
})

logger.V(1).Info("setting up with options", flags...)

evaluators.EvaluatorCacheSize = evaluatorCacheSize
metrics.DeepMetricsEnabled = deepMetricsEnabled

managerOptions := ctrl.Options{
Scheme: scheme,
Expand Down Expand Up @@ -319,7 +308,7 @@ func startExtAuthServerGRPC(authConfigIndex index.Index) {

grpcServer := grpc.NewServer(grpcServerOpts...)

envoy_auth.RegisterAuthorizationServer(grpcServer, &service.AuthService{Index: authConfigIndex, Timeout: timeoutMs})
envoy_auth.RegisterAuthorizationServer(grpcServer, &service.AuthService{Index: authConfigIndex, Timeout: timeoutMs()})
healthpb.RegisterHealthServer(grpcServer, &service.HealthService{})
grpc_prometheus.Register(grpcServer)
grpc_prometheus.EnableHandlingTimeHistogram()
Expand All @@ -335,14 +324,14 @@ func startExtAuthServerGRPC(authConfigIndex index.Index) {
}

func startExtAuthServerHTTP(authConfigIndex index.Index) {
startHTTPService("auth", extAuthHTTPPort, service.HTTPAuthorizationBasePath, tlsCertPath, tlsCertKeyPath, service.NewAuthService(authConfigIndex, timeoutMs, maxHttpRequestBodySize))
startHTTPService("auth", extAuthHTTPPort, service.HTTPAuthorizationBasePath, tlsCertPath, tlsCertKeyPath, service.NewAuthService(authConfigIndex, timeoutMs(), maxHttpRequestBodySize))
}

func startOIDCServer(authConfigIndex index.Index) {
startHTTPService("oidc", oidcHTTPPort, service.OIDCBasePath, oidcTLSCertPath, oidcTLSCertKeyPath, &service.OidcService{Index: authConfigIndex})
}

func startHTTPService(name, port, basePath, tlsCertPath, tlsCertKeyPath string, handler http.Handler) {
func startHTTPService(name string, port int, basePath, tlsCertPath, tlsCertKeyPath string, handler http.Handler) {
lis, err := listen(port)

if err != nil {
Expand Down Expand Up @@ -383,23 +372,31 @@ func startHTTPService(name, port, basePath, tlsCertPath, tlsCertKeyPath string,
}()
}

func listen(port string) (net.Listener, error) {
if p, err := strconv.Atoi(port); err != nil || p == 0 {
func listen(port int) (net.Listener, error) {
if port == 0 {
return nil, nil
}

if lis, err := net.Listen("tcp", ":"+port); err != nil {
if lis, err := net.Listen("tcp", fmt.Sprintf(":%d", port)); err != nil {
return nil, err
} else {
return lis, nil
}
}

func fetchEnv(key string, def string) string {
func fetchEnv(key string, def interface{}) string {
val, ok := os.LookupEnv(key)
if !ok {
return def
return fmt.Sprint(def)
} else {
return val
}
}

func timeoutMs() time.Duration {
return time.Duration(timeout) * time.Millisecond
}

func printVersion(_ *cobra.Command, _ []string) {
fmt.Println("Authorino", version)
}
33 changes: 33 additions & 0 deletions pkg/utils/envvar.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package utils

import (
"os"
"reflect"
"strconv"
)

type envVar interface {
string | int | int64 | bool
}

func EnvVar[T envVar](key string, def T) T {
val, ok := os.LookupEnv(key)
if !ok {
return def
} else {
switch reflect.ValueOf(def).Kind() {
case reflect.String:
return any(val).(T)
case reflect.Int:
v, _ := strconv.Atoi(val)
return any(v).(T)
case reflect.Int64:
v, _ := strconv.ParseInt(val, 10, 64)
return any(v).(T)
case reflect.Bool:
v, _ := strconv.ParseBool(val)
return any(v).(T)
}
return any(nil).(T)
}
}
Loading

0 comments on commit 3ba0baa

Please sign in to comment.