Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: v1.24.0
go-version: v1.25.4
- uses: actions/setup-node@v4
with:
node-version: '20'
Expand All @@ -45,7 +45,7 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: v1.24.0
go-version: v1.25.4
- uses: actions/setup-node@v4
with:
node-version: '20'
Expand All @@ -60,7 +60,7 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: v1.24.0
go-version: v1.25.4
- run: make test

lint:
Expand All @@ -70,7 +70,7 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: v1.24.0
go-version: v1.25.4
- run: make lint

verify:
Expand All @@ -80,5 +80,5 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: v1.24.0
go-version: v1.25.4
- run: make verify
2 changes: 1 addition & 1 deletion .github/workflows/docs-gen-and-push.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:

- uses: actions/setup-go@v5
with:
go-version: v1.24.0
go-version: v1.25.4
cache: true

- uses: actions/setup-python@v5
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
fetch-depth: 0
- uses: actions/setup-go@v5
with:
go-version: v1.24.0
go-version: v1.25.4
- name: Delete non-semver tags
run: 'git tag -d $(git tag -l | grep -v "^v")'
- name: Run GoReleaser on tag
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/image.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: v1.24.0
go-version: v1.25.4
check-latest: true

# We need this to remove local tags that are not semver so goreleaser doesn't get confused.
Expand Down
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ apiserviceexport.yaml
# Frontend dependencies and build
web/node_modules/
web/.vite/
web/*.tsbuildinfo
web/*.tsbuildinfo
go.work
go.work.sum
2 changes: 1 addition & 1 deletion .ko.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
baseImageOverrides:
github.com/google/ko: golang:1.24.0
github.com/google/ko: golang:1.25.4

builds:
- id: konnector
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ ENV VITE_BUILD_TARGET=docker
RUN npm run build

# Build Go binary with embedded UI assets
FROM golang:1.24.0 AS go-build-env
FROM golang:1.25.4 AS go-build-env
WORKDIR /app

# Accept build arguments for multi-arch support
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile.konnector
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

FROM golang:1.24.0 AS builder
FROM golang:1.25.4 AS builder
WORKDIR /app

# Accept build arguments for multi-arch support
Expand Down
7 changes: 1 addition & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -171,11 +171,6 @@ fix-lint: $(GOLANGCI_LINT) ## Run golangci-lint with --fix
GOLANGCI_LINT_FLAGS="--fix" $(MAKE) lint
.PHONY: fix-lint

vendor: ## Vendor the dependencies
go mod tidy
go mod vendor
.PHONY: vendor

tools: $(GOLANGCI_LINT) $(CONTROLLER_GEN) $(YAML_PATCH) $(GOTESTSUM) $(CODE_GENERATOR) ## Install tools
.PHONY: tools

Expand Down Expand Up @@ -364,7 +359,7 @@ verify-modules: modules # Verify go modules are up to date
done

.PHONY: verify
verify: verify-modules verify-go-versions verify-imports verify-codegen verify-boilerplate ## verify formal properties of the code
verify: verify-go-versions verify-imports verify-codegen verify-boilerplate ## verify formal properties of the code

.PHONY: help
help: ## Show this help
Expand Down
43 changes: 39 additions & 4 deletions backend/auth/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package auth

import (
"context"
"encoding/base64"
"encoding/json"
"errors"
Expand All @@ -34,14 +35,23 @@ import (
"github.com/kube-bind/kube-bind/backend/session"
)

type OIDCProvider interface {
GetOIDCProvider(ctx context.Context) (*OIDCServiceProvider, error)
}

type AuthHandlerInterface interface {
HandleAuthorize(w http.ResponseWriter, r *http.Request)
HandleCallback(w http.ResponseWriter, r *http.Request)
}

type AuthHandler struct {
oidc *OIDCServiceProvider
oidc OIDCProvider
jwtService *JWTService
cookieSigningKey []byte
cookieEncryptionKey []byte
}

func NewAuthHandler(oidc *OIDCServiceProvider, jwtService *JWTService, cookieSigningKey, cookieEncryptionKey []byte) *AuthHandler {
func NewAuthHandler(oidc OIDCProvider, jwtService *JWTService, cookieSigningKey, cookieEncryptionKey []byte) *AuthHandler {
return &AuthHandler{
oidc: oidc,
jwtService: jwtService,
Expand Down Expand Up @@ -85,8 +95,15 @@ func (ah *AuthHandler) HandleAuthorize(w http.ResponseWriter, r *http.Request) {
return
}

provider, err := ah.oidc.GetOIDCProvider(r.Context())
if err != nil {
logger.Info("failed to get OIDC provider", "error", err)
ah.respondWithError(w, authReq.ClientType, err.Error(), http.StatusInternalServerError)
return
}

encoded := base64.URLEncoding.EncodeToString(dataCode)
authURL := ah.oidc.OIDCProviderConfig(scopes).AuthCodeURL(encoded)
authURL := provider.OIDCProviderConfig(scopes).AuthCodeURL(encoded)

http.Redirect(w, r, authURL, http.StatusFound)
}
Expand Down Expand Up @@ -133,7 +150,25 @@ func (ah *AuthHandler) HandleCallback(w http.ResponseWriter, r *http.Request) {
return
}

token, err := ah.oidc.OIDCProviderConfig(nil).Exchange(r.Context(), code)
provider, err := ah.oidc.GetOIDCProvider(r.Context())
if err != nil {
logger.Info("failed to get OIDC provider", "error", err)
ah.respondWithError(w, authCode.ClientType, err.Error(), http.StatusInternalServerError)
return
}

// Create context with custom HTTP client if TLS config is available
ctx := r.Context()
if tlsConfig := provider.GetTLSConfig(); tlsConfig != nil {
client := &http.Client{
Transport: &http.Transport{
TLSClientConfig: tlsConfig,
},
}
ctx = context.WithValue(ctx, oauth2.HTTPClient, client)
}

token, err := provider.OIDCProviderConfig(nil).Exchange(ctx, code)
if err != nil {
logger.Error(err, "failed to exchange token")
http.Error(w, "internal error", http.StatusInternalServerError)
Expand Down
47 changes: 44 additions & 3 deletions backend/auth/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ package auth

import (
"context"
"crypto/tls"
"net/http"
"time"

oidc "github.com/coreos/go-oidc/v3/oidc"
Expand Down Expand Up @@ -67,8 +69,9 @@ type OIDCServiceProvider struct {
redirectURI string
issuerURL string

verifier *oidc.IDTokenVerifier
provider *oidc.Provider
verifier *oidc.IDTokenVerifier
provider *oidc.Provider
tlsConfig *tls.Config
}

func NewOIDCServiceProvider(ctx context.Context, clientID, clientSecret, redirectURI, issuerURL string) (*OIDCServiceProvider, error) {
Expand All @@ -84,15 +87,53 @@ func NewOIDCServiceProvider(ctx context.Context, clientID, clientSecret, redirec
issuerURL: issuerURL,
provider: provider,
verifier: provider.Verifier(&oidc.Config{ClientID: clientID}),
tlsConfig: nil,
}, nil
}

func NewOIDCServiceProviderWithTLS(
ctx context.Context,
clientID, clientSecret, redirectURI, issuerURL string,
tlsConfig *tls.Config,
) (*OIDCServiceProvider, error) {
// Create a custom HTTP client that trusts the TLS config
client := &http.Client{
Transport: &http.Transport{
TLSClientConfig: tlsConfig,
},
}

// Create context with the custom client
ctxWithClient := oidc.ClientContext(ctx, client)

provider, err := oidc.NewProvider(ctxWithClient, issuerURL)
if err != nil {
return nil, err
}

return &OIDCServiceProvider{
clientID: clientID,
clientSecret: clientSecret,
redirectURI: redirectURI,
issuerURL: issuerURL,
provider: provider,
verifier: provider.Verifier(&oidc.Config{ClientID: clientID}),
tlsConfig: tlsConfig,
}, nil
}

func (o *OIDCServiceProvider) OIDCProviderConfig(scopes []string) *oauth2.Config {
return &oauth2.Config{
config := &oauth2.Config{
ClientID: o.clientID,
ClientSecret: o.clientSecret,
Endpoint: o.provider.Endpoint(),
RedirectURL: o.redirectURI,
Scopes: scopes,
}

return config
}

func (o *OIDCServiceProvider) GetTLSConfig() *tls.Config {
return o.tlsConfig
}
20 changes: 14 additions & 6 deletions backend/http/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (
"github.com/kube-bind/kube-bind/backend/auth"
"github.com/kube-bind/kube-bind/backend/client"
"github.com/kube-bind/kube-bind/backend/kubernetes"
"github.com/kube-bind/kube-bind/backend/oidc"
"github.com/kube-bind/kube-bind/backend/spaserver"
bindversion "github.com/kube-bind/kube-bind/pkg/version"
kubebindv1alpha2 "github.com/kube-bind/kube-bind/sdk/apis/kubebind/v1alpha2"
Expand All @@ -48,8 +49,8 @@ var noCacheHeaders = map[string]string{
}

type handler struct {
oidc *auth.OIDCServiceProvider
authHandler *auth.AuthHandler
oidcProvider auth.OIDCProvider
authHandler auth.AuthHandlerInterface
authMiddleware *auth.AuthMiddleware

scope kubebindv1alpha2.InformerScope
Expand All @@ -64,12 +65,14 @@ type handler struct {

client *http.Client
kubeManager *kubernetes.Manager
oidcServer *oidc.Server

frontend string
}

func NewHandler(
provider *auth.OIDCServiceProvider,
oidcProvider auth.OIDCProvider,
oidcServer *oidc.Server,
oidcAuthorizeURL, backendCallbackURL, providerPrettyName, testingAutoSelect string,
cookieSigningKey, cookieEncryptionKey []byte,
schemaSource string,
Expand All @@ -83,14 +86,14 @@ func NewHandler(
return nil, fmt.Errorf("failed to create JWT service: %w", err)
}

// Create auth handler for generic authentication flows
authHandler := auth.NewAuthHandler(provider, jwtService, cookieSigningKey, cookieEncryptionKey)
// Create auth handler with OIDC provider
authHandler := auth.NewAuthHandler(oidcProvider, jwtService, cookieSigningKey, cookieEncryptionKey)

// Create auth middleware for request authentication
authMiddleware := auth.NewAuthMiddleware(jwtService, cookieSigningKey, cookieEncryptionKey)

return &handler{
oidc: provider,
oidcProvider: oidcProvider,
authHandler: authHandler,
authMiddleware: authMiddleware,
oidcAuthorizeURL: oidcAuthorizeURL,
Expand All @@ -104,6 +107,7 @@ func NewHandler(
kubeManager: mgr,
cookieSigningKey: cookieSigningKey,
cookieEncryptionKey: cookieEncryptionKey,
oidcServer: oidcServer,
}, nil
}

Expand All @@ -129,6 +133,10 @@ func (h *handler) AddRoutes(mux *mux.Router) error {
apiRouter.Handle("/bind", auth.RequireAuth(http.HandlerFunc(h.handleBind))).Methods(http.MethodPost)
apiRouter.Handle("/ping", auth.RequireAuth(http.HandlerFunc(h.handlePing))).Methods(http.MethodGet)

if h.oidcServer != nil {
h.oidcServer.AddRoutes(mux)
}

switch {
// Development mode: proxy to frontend dev server
case strings.HasPrefix(h.frontend, "http://"):
Expand Down
20 changes: 3 additions & 17 deletions backend/http/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (
"log"
"net"
"net/http"
"strconv"
"time"

"github.com/gorilla/mux"
Expand All @@ -37,22 +36,9 @@ type Server struct {

func NewServer(options *options.Serve) (*Server, error) {
server := &Server{
options: options,
Router: mux.NewRouter(),
}

if options.Listener == nil {
var err error
addr := options.ListenAddress
if options.ListenIP != "" {
addr = net.JoinHostPort(options.ListenIP, strconv.Itoa(options.ListenPort))
}
server.listener, err = net.Listen("tcp", addr)
if err != nil {
return nil, err
}
} else {
server.listener = options.Listener
options: options,
Router: mux.NewRouter(),
listener: options.Listener,
}

return server, nil
Expand Down
Loading