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
11 changes: 11 additions & 0 deletions api/v1alpha1/client_helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package v1alpha1

import "strings"

func (c *Client) Username(prefix string) string {
if c.Spec.Username != nil {
return *c.Spec.Username
} else {
return prefix + strings.Join([]string{"client", c.Namespace, c.Name, string(c.UID)}, ":")
}
}
11 changes: 11 additions & 0 deletions api/v1alpha1/exporter_helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package v1alpha1

import "strings"

func (e *Exporter) Username(prefix string) string {
if e.Spec.Username != nil {
return *e.Spec.Username
} else {
return prefix + strings.Join([]string{"exporter", e.Namespace, e.Name, string(e.UID)}, ":")
}
}
24 changes: 3 additions & 21 deletions internal/authorization/basic.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ type BasicAuthorizer struct {
prefix string
}

func NewBasicAuthorizer(reader client.Reader, prefix string) *BasicAuthorizer {
func NewBasicAuthorizer(reader client.Reader, prefix string) authorizer.Authorizer {
return &BasicAuthorizer{reader: reader, prefix: prefix}
}

Expand All @@ -30,7 +30,7 @@ func (b *BasicAuthorizer) Authorize(
}, &e); err != nil {
return authorizer.DecisionDeny, "failed to get exporter", err
}
if ExporterAuthorizedUsername(&e, b.prefix) == attributes.GetUser().GetName() {
if e.Username(b.prefix) == attributes.GetUser().GetName() {
return authorizer.DecisionAllow, "", nil
} else {
return authorizer.DecisionDeny, "", nil
Expand All @@ -43,7 +43,7 @@ func (b *BasicAuthorizer) Authorize(
}, &c); err != nil {
return authorizer.DecisionDeny, "failed to get client", err
}
if ClientAuthorizedUsername(&c, b.prefix) == attributes.GetUser().GetName() {
if c.Username(b.prefix) == attributes.GetUser().GetName() {
return authorizer.DecisionAllow, "", nil
} else {
return authorizer.DecisionDeny, "", nil
Expand All @@ -52,21 +52,3 @@ func (b *BasicAuthorizer) Authorize(
return authorizer.DecisionDeny, "invalid object kind", nil
}
}

func ClientAuthorizedUsername(c *jumpstarterdevv1alpha1.Client, prefix string) string {
if c.Spec.Username == nil {
return prefix + "client:" + c.Namespace + ":" + c.Name + ":" + string(c.UID)
} else {
return *c.Spec.Username
}
}

func ExporterAuthorizedUsername(e *jumpstarterdevv1alpha1.Exporter, prefix string) string {
if e.Spec.Username == nil {
return prefix + "exporter:" + e.Namespace + ":" + e.Name + ":" + string(e.UID)
} else {
return *e.Spec.Username
}
}

var _ = authorizer.Authorizer(&BasicAuthorizer{})
5 changes: 2 additions & 3 deletions internal/controller/client_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import (
"sigs.k8s.io/controller-runtime/pkg/log"

jumpstarterdevv1alpha1 "github.com/jumpstarter-dev/jumpstarter-controller/api/v1alpha1"
"github.com/jumpstarter-dev/jumpstarter-controller/internal/authorization"
"github.com/jumpstarter-dev/jumpstarter-controller/internal/oidc"
)

Expand Down Expand Up @@ -94,7 +93,7 @@ func (r *ClientReconciler) clientSecretExists(
}

token, ok := secret.Data["token"]
if !ok || r.Signer.Verify(string(token)) != nil {
if !ok || r.Signer.UnsafeValidate(string(token)) != nil {
logger.Info("reconcileStatusCredential: the client secret is invalid", "client", client.Name)
return false, r.Delete(ctx, secret)
}
Expand Down Expand Up @@ -153,7 +152,7 @@ func (r *ClientReconciler) reconcileStatusEndpoint(
}

func (r *ClientReconciler) secretForClient(client *jumpstarterdevv1alpha1.Client) (*corev1.Secret, error) {
token, err := r.Signer.Token(authorization.ClientAuthorizedUsername(client, r.Signer.Prefix()))
token, err := r.Signer.Token(client.Username(r.Signer.Prefix()))
if err != nil {
return nil, err
}
Expand Down
5 changes: 2 additions & 3 deletions internal/controller/exporter_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import (
"sigs.k8s.io/controller-runtime/pkg/log"

jumpstarterdevv1alpha1 "github.com/jumpstarter-dev/jumpstarter-controller/api/v1alpha1"
"github.com/jumpstarter-dev/jumpstarter-controller/internal/authorization"
"github.com/jumpstarter-dev/jumpstarter-controller/internal/oidc"
)

Expand Down Expand Up @@ -107,7 +106,7 @@ func (r *ExporterReconciler) exporterSecretExists(

token, ok := secret.Data["token"]

if !ok || r.Signer.Verify(string(token)) != nil {
if !ok || r.Signer.UnsafeValidate(string(token)) != nil {
logger.Info("reconcileStatusCredential: the exporter secret is invalid", "exporter", exporter.Name)
return false, r.Delete(ctx, secret)
}
Expand Down Expand Up @@ -193,7 +192,7 @@ func (r *ExporterReconciler) reconcileStatusEndpoint(
}

func (r *ExporterReconciler) secretForExporter(exporter *jumpstarterdevv1alpha1.Exporter) (*corev1.Secret, error) {
token, err := r.Signer.Token(authorization.ExporterAuthorizedUsername(exporter, r.Signer.Prefix()))
token, err := r.Signer.Token(exporter.Username(r.Signer.Prefix()))
if err != nil {
return nil, err
}
Expand Down
15 changes: 10 additions & 5 deletions internal/oidc/op.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import (
"github.com/zitadel/oidc/v3/pkg/op"
)

const tokenPlaceholder string = "placeholder for external OIDC provider access token"

type Signer struct {
privatekey *ecdsa.PrivateKey
issuer string
Expand Down Expand Up @@ -90,7 +92,10 @@ func (k *Signer) Register(group gin.IRoutes) {
})
}

func (k *Signer) Verify(token string) error {
func (k *Signer) UnsafeValidate(token string) error {
if token == tokenPlaceholder {
return nil
}
_, err := jwt.Parse(token, func(t *jwt.Token) (interface{}, error) {
return &k.privatekey.PublicKey, nil
},
Expand All @@ -104,14 +109,14 @@ func (k *Signer) Verify(token string) error {
}

func (k *Signer) Token(
subject string,
username string,
) (string, error) {
if !strings.HasPrefix(subject, k.prefix) {
return "placeholder for external OIDC provider access token", nil
if !strings.HasPrefix(username, k.prefix) {
return tokenPlaceholder, nil
}
return jwt.NewWithClaims(jwt.SigningMethodES256, jwt.RegisteredClaims{
Issuer: k.issuer,
Subject: strings.TrimPrefix(subject, k.prefix),
Subject: strings.TrimPrefix(username, k.prefix),
Audience: []string{k.audience},
IssuedAt: jwt.NewNumericDate(time.Now()),
ExpiresAt: jwt.NewNumericDate(time.Now().Add(365 * 24 * time.Hour)), // FIXME: rotate keys on expiration
Expand Down