Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
12a1a39
only resolve URLs once instead of once per mapping
xrstf Jul 8, 2025
f84efcc
remove redundant and wrong status code handling
xrstf Jul 8, 2025
dc95aab
WIP: middleware to resolve clusters
xrstf Jul 11, 2025
d1e378f
Add WorkspaceAuthenticationConfiguration
xrstf Jul 11, 2025
2ee1d76
add reference to WAC to WorkspaceTypes
xrstf Jul 11, 2025
ca69948
keep track of workspace types per logicalcluster in the index
xrstf Jul 11, 2025
58ecc27
implement auth controller and auth index
xrstf Jul 11, 2025
41fd4d9
fix handling for local workspace types
xrstf Jul 11, 2025
c4ed4ce
tweak optionality of some fields
xrstf Jul 11, 2025
fc12b5d
codegen
xrstf Jul 14, 2025
727847f
introduce new WorkspaceAuthentication feature gate
xrstf Jul 14, 2025
19a9409
remove Path option for WorkspaceAuthConfig references
xrstf Jul 31, 2025
948c924
fix shard handling in the index, move code out of pkg/proxy/ to prepa…
xrstf Jul 31, 2025
b7c141a
add workspaceauth handling to localproxy, enabling a single-shard to …
xrstf Jul 31, 2025
16183bc
add basic e2e test to ensure custom authentication for a workspace works
xrstf Jul 31, 2025
b1f96fb
lint
xrstf Jul 31, 2025
8a1938d
enable feature in shared e2e tests
xrstf Aug 1, 2025
c64753f
fix multiple logic issues in authentication chain
xrstf Aug 1, 2025
7a89236
cleanup unit test
xrstf Aug 2, 2025
74e8a17
constraint testcase to new workspace to allow multiple runs
xrstf Aug 3, 2025
d247b51
cancel and stop shard watchers when servers are stopped
xrstf Aug 5, 2025
be2d5ff
remove unneeded parameter since we're now relying on the context
xrstf Aug 6, 2025
32a630f
improve error handling
xrstf Aug 6, 2025
5e8d9e2
rename ref field from Configuration to Name
xrstf Aug 6, 2025
39d6d4e
extend e2e testcases
xrstf Aug 6, 2025
242e852
scope authn infos to the given logicalcluster, add test to ensure it …
xrstf Aug 6, 2025
1c11747
add documentation
xrstf Aug 7, 2025
46b1c0c
prevent workspace authentication from returning system groups or names
xrstf Aug 15, 2025
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
7 changes: 4 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,8 @@ ifdef SUITES
SUITES_ARG = --suites $(SUITES)
COMPLETE_SUITES_ARG = -args $(SUITES_ARG)
endif
TEST_FEATURE_GATES ?= WorkspaceMounts=true,CacheAPIs=true
TEST_FEATURE_GATES ?= WorkspaceMounts=true,CacheAPIs=true,WorkspaceAuthentication=true
PROXY_FEATURE_GATES ?= $(TEST_FEATURE_GATES)

.PHONY: test-e2e
ifdef USE_GOTESTSUM
Expand Down Expand Up @@ -337,7 +338,7 @@ endif
test-e2e-sharded-minimal: build-all
mkdir -p "$(LOG_DIR)" "$(WORK_DIR)/.kcp"
rm -f "$(WORK_DIR)/.kcp/ready-to-test"
UNSAFE_E2E_HACK_DISABLE_ETCD_FSYNC=true NO_GORUN=1 ./bin/sharded-test-server --quiet --v=2 --log-dir-path="$(LOG_DIR)" --work-dir-path="$(WORK_DIR)" --shard-run-virtual-workspaces=false --shard-feature-gates=$(TEST_FEATURE_GATES) $(TEST_SERVER_ARGS) --number-of-shards=$(SHARDS) 2>&1 & PID=$$!; echo "PID $$PID" && \
UNSAFE_E2E_HACK_DISABLE_ETCD_FSYNC=true NO_GORUN=1 ./bin/sharded-test-server --quiet --v=2 --log-dir-path="$(LOG_DIR)" --work-dir-path="$(WORK_DIR)" --shard-run-virtual-workspaces=false --shard-feature-gates=$(TEST_FEATURE_GATES) --proxy-feature-gates=$(PROXY_FEATURE_GATES) $(TEST_SERVER_ARGS) --number-of-shards=$(SHARDS) 2>&1 & PID=$$!; echo "PID $$PID" && \
trap 'kill -TERM $$PID && wait $$PID' TERM INT EXIT && \
while [ ! -f "$(WORK_DIR)/.kcp/ready-to-test" ]; do sleep 1; done && \
echo 'Starting test(s)' && \
Expand All @@ -354,7 +355,7 @@ test-run-sharded-server: LOG_DIR ?= $(WORK_DIR)/.kcp
test-run-sharded-server:
mkdir -p "$(LOG_DIR)" "$(WORK_DIR)/.kcp"
rm -f "$(WORK_DIR)/.kcp/ready-to-test"
UNSAFE_E2E_HACK_DISABLE_ETCD_FSYNC=true NO_GORUN=1 ./bin/sharded-test-server --quiet --v=2 --log-dir-path="$(LOG_DIR)" --work-dir-path="$(WORK_DIR)" --shard-run-virtual-workspaces=false --shard-feature-gates=$(TEST_FEATURE_GATES) $(TEST_SERVER_ARGS) --number-of-shards=2 2>&1 & PID=$$!; echo "PID $$PID" && \
UNSAFE_E2E_HACK_DISABLE_ETCD_FSYNC=true NO_GORUN=1 ./bin/sharded-test-server --quiet --v=2 --log-dir-path="$(LOG_DIR)" --work-dir-path="$(WORK_DIR)" --shard-run-virtual-workspaces=false --shard-feature-gates=$(TEST_FEATURE_GATES) --proxy-feature-gates=$(PROXY_FEATURE_GATES) $(TEST_SERVER_ARGS) --number-of-shards=2 2>&1 & PID=$$!; echo "PID $$PID" && \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With second flag this looks strange now. 2 featureflags flags. Should we maybe get ticket to deprecate --shard-feature-gates in favor of --feature-gates and use use one everywhere?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because I needed to be able to control the feature independently between shard and front-proxy, because some tests are meant to ensure that the front-proxy does the authentication. That's why the sharded-test-server has a new CLI flag. The front-proxy's flag is called --feature-gate, like the shard's CLI flag is. Only on the test server do we need 2 sets of feature gates, hence 2 CLI flags.

trap 'kill -TERM $$PID && wait $$PID' TERM INT EXIT && \
while [ ! -f "$(WORK_DIR)/.kcp/ready-to-test" ]; do sleep 1; done && \
echo 'Server started' && \
Expand Down
8 changes: 8 additions & 0 deletions cmd/kcp-front-proxy/options/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@ limitations under the License.
package options

import (
"strings"

cliflag "k8s.io/component-base/cli/flag"
"k8s.io/component-base/logs"
logsapiv1 "k8s.io/component-base/logs/api/v1"

kcpfeatures "github.com/kcp-dev/kcp/pkg/features"
proxyoptions "github.com/kcp-dev/kcp/pkg/proxy/options"
)

Expand All @@ -43,6 +46,11 @@ func NewOptions() *Options {
func (o *Options) AddFlags(fss *cliflag.NamedFlagSets) {
o.Proxy.AddFlags(fss)
logsapiv1.AddFlags(o.Logs, fss.FlagSet("logging"))

// add flags that are filtered out from upstream, but overridden here with our own version
fss.FlagSet("KCP").Var(kcpfeatures.NewFlagValue(), "feature-gates", ""+
"A set of key=value pairs that describe feature gates for alpha/experimental features. "+
"Options are:\n"+strings.Join(kcpfeatures.KnownFeatures(), "\n")) // hide kube-only gates
}

func (o *Options) Complete() error {
Expand Down
208 changes: 208 additions & 0 deletions config/crds/tenancy.kcp.io_workspaceauthenticationconfigurations.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.17.3
name: workspaceauthenticationconfigurations.tenancy.kcp.io
spec:
group: tenancy.kcp.io
names:
categories:
- kcp
kind: WorkspaceAuthenticationConfiguration
listKind: WorkspaceAuthenticationConfigurationList
plural: workspaceauthenticationconfigurations
singular: workspaceauthenticationconfiguration
scope: Cluster
versions:
- name: v1alpha1
schema:
openAPIV3Schema:
description: |-
WorkspaceAuthenticationConfiguration specifies additional authentication options
for workspaces.
properties:
apiVersion:
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
spec:
properties:
jwt:
items:
properties:
claimMappings:
description: ClaimMappings provides the configuration for claim
mapping.
properties:
extra:
items:
description: ExtraMapping provides the configuration for
a single extra mapping.
properties:
key:
type: string
valueExpression:
type: string
required:
- key
- valueExpression
type: object
type: array
groups:
description: PrefixedClaimOrExpression provides the configuration
for a single prefixed claim or expression.
properties:
claim:
type: string
expression:
type: string
prefix:
type: string
required:
- claim
type: object
uid:
description: ClaimOrExpression provides the configuration
for a single claim or expression.
properties:
claim:
type: string
expression:
type: string
required:
- claim
type: object
username:
description: PrefixedClaimOrExpression provides the configuration
for a single prefixed claim or expression.
properties:
claim:
type: string
expression:
type: string
prefix:
type: string
required:
- claim
type: object
required:
- groups
- username
type: object
claimValidationRules:
items:
description: ClaimValidationRule provides the configuration
for a single claim validation rule.
properties:
claim:
type: string
expression:
type: string
message:
type: string
requiredValue:
type: string
required:
- claim
- expression
- message
- requiredValue
type: object
type: array
issuer:
description: Issuer provides the configuration for an external
provider's specific settings.
properties:
audienceMatchPolicy:
description: AudienceMatchPolicyType is a set of valid values
for Issuer.AudienceMatchPolicy.
type: string
audiences:
items:
type: string
type: array
certificateAuthority:
type: string
discoveryURL:
description: |-
discoveryURL, if specified, overrides the URL used to fetch discovery
information instead of using "{url}/.well-known/openid-configuration".
The exact value specified is used, so "/.well-known/openid-configuration"
must be included in discoveryURL if needed.

The "issuer" field in the fetched discovery information must match the "issuer.url" field
in the AuthenticationConfiguration and will be used to validate the "iss" claim in the presented JWT.
This is for scenarios where the well-known and jwks endpoints are hosted at a different
location than the issuer (such as locally in the cluster).

Example:
A discovery url that is exposed using kubernetes service 'oidc' in namespace 'oidc-namespace'
and discovery information is available at '/.well-known/openid-configuration'.
discoveryURL: "https://oidc.oidc-namespace/.well-known/openid-configuration"
certificateAuthority is used to verify the TLS connection and the hostname on the leaf certificate
must be set to 'oidc.oidc-namespace'.

curl https://oidc.oidc-namespace/.well-known/openid-configuration (.discoveryURL field)
{
issuer: "https://oidc.example.com" (.url field)
}

discoveryURL must be different from url.
Required to be unique across all JWT authenticators.
Note that egress selection configuration is not used for this network connection.
type: string
url:
description: |-
url points to the issuer URL in a format https://url or https://url/path.
This must match the "iss" claim in the presented JWT, and the issuer returned from discovery.
Same value as the --oidc-issuer-url flag.
Discovery information is fetched from "{url}/.well-known/openid-configuration" unless overridden by discoveryURL.
Required to be unique across all JWT authenticators.
Note that egress selection configuration is not used for this network connection.
type: string
required:
- url
type: object
userValidationRules:
items:
description: UserValidationRule provides the configuration
for a single user validation rule.
properties:
expression:
type: string
message:
type: string
required:
- expression
- message
type: object
type: array
required:
- claimMappings
- issuer
type: object
type: array
required:
- jwt
type: object
required:
- metadata
- spec
type: object
served: true
storage: true
15 changes: 15 additions & 0 deletions config/crds/tenancy.kcp.io_workspacetypes.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,21 @@ spec:
additionalWorkspaceLabels are a set of labels that will be added to a
Workspace on creation.
type: object
authenticationConfigurations:
description: |-
authenticationConfigurations are additional authentication options that should apply to any
workspace using this workspace type.
items:
description: AuthenticationConfigurationReference provides the fields
necessary to resolve a WorkspaceAuthenticationConfiguration.
properties:
name:
description: name is the name of the WorkspaceAuthenticationConfiguration.
type: string
required:
- name
type: object
type: array
defaultAPIBindingLifecycle:
description: Configure the lifecycle behaviour of defaultAPIBindings.
enum:
Expand Down
7 changes: 6 additions & 1 deletion config/root-phase0/apiexport-tenancy.kcp.io.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,19 @@ spec:
maximalPermissionPolicy:
local: {}
resources:
- group: tenancy.kcp.io
name: workspaceauthenticationconfigurations
schema: v250802-1b3cd3d0d.workspaceauthenticationconfigurations.tenancy.kcp.io
storage:
crd: {}
- group: tenancy.kcp.io
name: workspaces
schema: v250421-25d98218b.workspaces.tenancy.kcp.io
storage:
crd: {}
- group: tenancy.kcp.io
name: workspacetypes
schema: v250603-d4d365c8e.workspacetypes.tenancy.kcp.io
schema: v250806-4c99c4583.workspacetypes.tenancy.kcp.io
storage:
crd: {}
status: {}
Loading