Skip to content

Commit 339e173

Browse files
authored
Merge pull request #3481 from xrstf/per-workspace-authn
Per-workspace Authentication
2 parents 059a31b + 46b1c0c commit 339e173

File tree

71 files changed

+5126
-257
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+5126
-257
lines changed

Makefile

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,8 @@ ifdef SUITES
280280
SUITES_ARG = --suites $(SUITES)
281281
COMPLETE_SUITES_ARG = -args $(SUITES_ARG)
282282
endif
283-
TEST_FEATURE_GATES ?= WorkspaceMounts=true,CacheAPIs=true
283+
TEST_FEATURE_GATES ?= WorkspaceMounts=true,CacheAPIs=true,WorkspaceAuthentication=true
284+
PROXY_FEATURE_GATES ?= $(TEST_FEATURE_GATES)
284285

285286
.PHONY: test-e2e
286287
ifdef USE_GOTESTSUM
@@ -337,7 +338,7 @@ endif
337338
test-e2e-sharded-minimal: build-all
338339
mkdir -p "$(LOG_DIR)" "$(WORK_DIR)/.kcp"
339340
rm -f "$(WORK_DIR)/.kcp/ready-to-test"
340-
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" && \
341+
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" && \
341342
trap 'kill -TERM $$PID && wait $$PID' TERM INT EXIT && \
342343
while [ ! -f "$(WORK_DIR)/.kcp/ready-to-test" ]; do sleep 1; done && \
343344
echo 'Starting test(s)' && \
@@ -354,7 +355,7 @@ test-run-sharded-server: LOG_DIR ?= $(WORK_DIR)/.kcp
354355
test-run-sharded-server:
355356
mkdir -p "$(LOG_DIR)" "$(WORK_DIR)/.kcp"
356357
rm -f "$(WORK_DIR)/.kcp/ready-to-test"
357-
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" && \
358+
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" && \
358359
trap 'kill -TERM $$PID && wait $$PID' TERM INT EXIT && \
359360
while [ ! -f "$(WORK_DIR)/.kcp/ready-to-test" ]; do sleep 1; done && \
360361
echo 'Server started' && \

cmd/kcp-front-proxy/options/options.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,13 @@ limitations under the License.
1717
package options
1818

1919
import (
20+
"strings"
21+
2022
cliflag "k8s.io/component-base/cli/flag"
2123
"k8s.io/component-base/logs"
2224
logsapiv1 "k8s.io/component-base/logs/api/v1"
2325

26+
kcpfeatures "github.com/kcp-dev/kcp/pkg/features"
2427
proxyoptions "github.com/kcp-dev/kcp/pkg/proxy/options"
2528
)
2629

@@ -43,6 +46,11 @@ func NewOptions() *Options {
4346
func (o *Options) AddFlags(fss *cliflag.NamedFlagSets) {
4447
o.Proxy.AddFlags(fss)
4548
logsapiv1.AddFlags(o.Logs, fss.FlagSet("logging"))
49+
50+
// add flags that are filtered out from upstream, but overridden here with our own version
51+
fss.FlagSet("KCP").Var(kcpfeatures.NewFlagValue(), "feature-gates", ""+
52+
"A set of key=value pairs that describe feature gates for alpha/experimental features. "+
53+
"Options are:\n"+strings.Join(kcpfeatures.KnownFeatures(), "\n")) // hide kube-only gates
4654
}
4755

4856
func (o *Options) Complete() error {
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
---
2+
apiVersion: apiextensions.k8s.io/v1
3+
kind: CustomResourceDefinition
4+
metadata:
5+
annotations:
6+
controller-gen.kubebuilder.io/version: v0.17.3
7+
name: workspaceauthenticationconfigurations.tenancy.kcp.io
8+
spec:
9+
group: tenancy.kcp.io
10+
names:
11+
categories:
12+
- kcp
13+
kind: WorkspaceAuthenticationConfiguration
14+
listKind: WorkspaceAuthenticationConfigurationList
15+
plural: workspaceauthenticationconfigurations
16+
singular: workspaceauthenticationconfiguration
17+
scope: Cluster
18+
versions:
19+
- name: v1alpha1
20+
schema:
21+
openAPIV3Schema:
22+
description: |-
23+
WorkspaceAuthenticationConfiguration specifies additional authentication options
24+
for workspaces.
25+
properties:
26+
apiVersion:
27+
description: |-
28+
APIVersion defines the versioned schema of this representation of an object.
29+
Servers should convert recognized schemas to the latest internal value, and
30+
may reject unrecognized values.
31+
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
32+
type: string
33+
kind:
34+
description: |-
35+
Kind is a string value representing the REST resource this object represents.
36+
Servers may infer this from the endpoint the client submits requests to.
37+
Cannot be updated.
38+
In CamelCase.
39+
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
40+
type: string
41+
metadata:
42+
type: object
43+
spec:
44+
properties:
45+
jwt:
46+
items:
47+
properties:
48+
claimMappings:
49+
description: ClaimMappings provides the configuration for claim
50+
mapping.
51+
properties:
52+
extra:
53+
items:
54+
description: ExtraMapping provides the configuration for
55+
a single extra mapping.
56+
properties:
57+
key:
58+
type: string
59+
valueExpression:
60+
type: string
61+
required:
62+
- key
63+
- valueExpression
64+
type: object
65+
type: array
66+
groups:
67+
description: PrefixedClaimOrExpression provides the configuration
68+
for a single prefixed claim or expression.
69+
properties:
70+
claim:
71+
type: string
72+
expression:
73+
type: string
74+
prefix:
75+
type: string
76+
required:
77+
- claim
78+
type: object
79+
uid:
80+
description: ClaimOrExpression provides the configuration
81+
for a single claim or expression.
82+
properties:
83+
claim:
84+
type: string
85+
expression:
86+
type: string
87+
required:
88+
- claim
89+
type: object
90+
username:
91+
description: PrefixedClaimOrExpression provides the configuration
92+
for a single prefixed claim or expression.
93+
properties:
94+
claim:
95+
type: string
96+
expression:
97+
type: string
98+
prefix:
99+
type: string
100+
required:
101+
- claim
102+
type: object
103+
required:
104+
- groups
105+
- username
106+
type: object
107+
claimValidationRules:
108+
items:
109+
description: ClaimValidationRule provides the configuration
110+
for a single claim validation rule.
111+
properties:
112+
claim:
113+
type: string
114+
expression:
115+
type: string
116+
message:
117+
type: string
118+
requiredValue:
119+
type: string
120+
required:
121+
- claim
122+
- expression
123+
- message
124+
- requiredValue
125+
type: object
126+
type: array
127+
issuer:
128+
description: Issuer provides the configuration for an external
129+
provider's specific settings.
130+
properties:
131+
audienceMatchPolicy:
132+
description: AudienceMatchPolicyType is a set of valid values
133+
for Issuer.AudienceMatchPolicy.
134+
type: string
135+
audiences:
136+
items:
137+
type: string
138+
type: array
139+
certificateAuthority:
140+
type: string
141+
discoveryURL:
142+
description: |-
143+
discoveryURL, if specified, overrides the URL used to fetch discovery
144+
information instead of using "{url}/.well-known/openid-configuration".
145+
The exact value specified is used, so "/.well-known/openid-configuration"
146+
must be included in discoveryURL if needed.
147+
148+
The "issuer" field in the fetched discovery information must match the "issuer.url" field
149+
in the AuthenticationConfiguration and will be used to validate the "iss" claim in the presented JWT.
150+
This is for scenarios where the well-known and jwks endpoints are hosted at a different
151+
location than the issuer (such as locally in the cluster).
152+
153+
Example:
154+
A discovery url that is exposed using kubernetes service 'oidc' in namespace 'oidc-namespace'
155+
and discovery information is available at '/.well-known/openid-configuration'.
156+
discoveryURL: "https://oidc.oidc-namespace/.well-known/openid-configuration"
157+
certificateAuthority is used to verify the TLS connection and the hostname on the leaf certificate
158+
must be set to 'oidc.oidc-namespace'.
159+
160+
curl https://oidc.oidc-namespace/.well-known/openid-configuration (.discoveryURL field)
161+
{
162+
issuer: "https://oidc.example.com" (.url field)
163+
}
164+
165+
discoveryURL must be different from url.
166+
Required to be unique across all JWT authenticators.
167+
Note that egress selection configuration is not used for this network connection.
168+
type: string
169+
url:
170+
description: |-
171+
url points to the issuer URL in a format https://url or https://url/path.
172+
This must match the "iss" claim in the presented JWT, and the issuer returned from discovery.
173+
Same value as the --oidc-issuer-url flag.
174+
Discovery information is fetched from "{url}/.well-known/openid-configuration" unless overridden by discoveryURL.
175+
Required to be unique across all JWT authenticators.
176+
Note that egress selection configuration is not used for this network connection.
177+
type: string
178+
required:
179+
- url
180+
type: object
181+
userValidationRules:
182+
items:
183+
description: UserValidationRule provides the configuration
184+
for a single user validation rule.
185+
properties:
186+
expression:
187+
type: string
188+
message:
189+
type: string
190+
required:
191+
- expression
192+
- message
193+
type: object
194+
type: array
195+
required:
196+
- claimMappings
197+
- issuer
198+
type: object
199+
type: array
200+
required:
201+
- jwt
202+
type: object
203+
required:
204+
- metadata
205+
- spec
206+
type: object
207+
served: true
208+
storage: true

config/crds/tenancy.kcp.io_workspacetypes.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,21 @@ spec:
5656
additionalWorkspaceLabels are a set of labels that will be added to a
5757
Workspace on creation.
5858
type: object
59+
authenticationConfigurations:
60+
description: |-
61+
authenticationConfigurations are additional authentication options that should apply to any
62+
workspace using this workspace type.
63+
items:
64+
description: AuthenticationConfigurationReference provides the fields
65+
necessary to resolve a WorkspaceAuthenticationConfiguration.
66+
properties:
67+
name:
68+
description: name is the name of the WorkspaceAuthenticationConfiguration.
69+
type: string
70+
required:
71+
- name
72+
type: object
73+
type: array
5974
defaultAPIBindingLifecycle:
6075
description: Configure the lifecycle behaviour of defaultAPIBindings.
6176
enum:

config/root-phase0/apiexport-tenancy.kcp.io.yaml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,19 @@ spec:
77
maximalPermissionPolicy:
88
local: {}
99
resources:
10+
- group: tenancy.kcp.io
11+
name: workspaceauthenticationconfigurations
12+
schema: v250802-1b3cd3d0d.workspaceauthenticationconfigurations.tenancy.kcp.io
13+
storage:
14+
crd: {}
1015
- group: tenancy.kcp.io
1116
name: workspaces
1217
schema: v250421-25d98218b.workspaces.tenancy.kcp.io
1318
storage:
1419
crd: {}
1520
- group: tenancy.kcp.io
1621
name: workspacetypes
17-
schema: v250603-d4d365c8e.workspacetypes.tenancy.kcp.io
22+
schema: v250806-4c99c4583.workspacetypes.tenancy.kcp.io
1823
storage:
1924
crd: {}
2025
status: {}

0 commit comments

Comments
 (0)