mirror of
https://github.com/cozystack/cozystack.git
synced 2026-03-05 14:38:57 +00:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e35d6ae4e | ||
|
|
2f8c6b72fe | ||
|
|
5a679e12ad | ||
|
|
0176ba5e95 | ||
|
|
b474c07c80 | ||
|
|
5dbdd0eafa | ||
|
|
21715c02bc |
@@ -64,19 +64,19 @@ spec:
|
||||
EOF
|
||||
# Wait for the tenant-test namespace to be active
|
||||
kubectl wait namespace tenant-test --timeout=20s --for=jsonpath='{.status.phase}'=Active
|
||||
|
||||
|
||||
# Wait for the Kamaji control plane to be created (retry for up to 10 seconds)
|
||||
timeout 10 sh -ec 'until kubectl get kamajicontrolplane -n tenant-test kubernetes-'"${test_name}"'; do sleep 1; done'
|
||||
|
||||
# Wait for the tenant control plane to be fully created (timeout after 4 minutes)
|
||||
kubectl wait --for=condition=TenantControlPlaneCreated kamajicontrolplane -n tenant-test kubernetes-${test_name} --timeout=4m
|
||||
|
||||
|
||||
# Wait for Kubernetes resources to be ready (timeout after 2 minutes)
|
||||
kubectl wait tcp -n tenant-test kubernetes-${test_name} --timeout=2m --for=jsonpath='{.status.kubernetesResources.version.status}'=Ready
|
||||
|
||||
|
||||
# Wait for all required deployments to be available (timeout after 4 minutes)
|
||||
kubectl wait deploy --timeout=4m --for=condition=available -n tenant-test kubernetes-${test_name} kubernetes-${test_name}-cluster-autoscaler kubernetes-${test_name}-kccm kubernetes-${test_name}-kcsi-controller
|
||||
|
||||
|
||||
# Wait for the machine deployment to scale to 2 replicas (timeout after 1 minute)
|
||||
kubectl wait machinedeployment kubernetes-${test_name}-md0 -n tenant-test --timeout=1m --for=jsonpath='{.status.replicas}'=2
|
||||
# Get the admin kubeconfig and save it to a file
|
||||
@@ -105,9 +105,11 @@ EOF
|
||||
versions=$(kubectl --kubeconfig tenantkubeconfig get nodes -o jsonpath='{.items[*].status.nodeInfo.kubeletVersion}')
|
||||
node_ok=true
|
||||
|
||||
if [[ "$k8s_version" == v1.32* ]]; then
|
||||
echo "⚠️ TODO: Temporary stub — allowing nodes with v1.33 while k8s_version is v1.32"
|
||||
fi
|
||||
case "$k8s_version" in
|
||||
v1.32*)
|
||||
echo "⚠️ TODO: Temporary stub — allowing nodes with v1.33 while k8s_version is v1.32"
|
||||
;;
|
||||
esac
|
||||
|
||||
for v in $versions; do
|
||||
case "$k8s_version" in
|
||||
@@ -134,7 +136,7 @@ EOF
|
||||
esac
|
||||
done
|
||||
|
||||
if ! $node_ok; then
|
||||
if [ "$node_ok" != true ]; then
|
||||
echo "Kubelet versions did not match expected ${k8s_version}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -1 +1 @@
|
||||
ghcr.io/cozystack/cozystack/nginx-cache:0.0.0@sha256:50ac1581e3100bd6c477a71161cb455a341ffaf9e5e2f6086802e4e25271e8af
|
||||
ghcr.io/cozystack/cozystack/nginx-cache:0.0.0@sha256:e0a07082bb6fc6aeaae2315f335386f1705a646c72f9e0af512aebbca5cb2b15
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
cozystack:
|
||||
image: ghcr.io/cozystack/cozystack/installer:v0.37.0@sha256:256c5a0f0ae2fc3ad6865b9fda74c42945b38a5384240fa29554617185b60556
|
||||
image: ghcr.io/cozystack/cozystack/installer:v0.37.1@sha256:67aa398836ad240a3af3c4108ef61c36c1ba11989ab9fbc1d5f003456dcc949c
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
e2e:
|
||||
image: ghcr.io/cozystack/cozystack/e2e-sandbox:v0.37.0@sha256:10afd0a6c39248ec41d0e59ff1bc6c29bd0075b7cc9a512b01cf603ef39c33ea
|
||||
image: ghcr.io/cozystack/cozystack/e2e-sandbox:v0.37.1@sha256:82e42c2416d6704786d37920d162416efc02083a1c30605d22b8213198b515a8
|
||||
|
||||
@@ -1 +1 @@
|
||||
ghcr.io/cozystack/cozystack/matchbox:v0.37.0@sha256:5cca5f56b755285aefa11b1052fe55e1aa83b25bae34aef80cdb77ff63091044
|
||||
ghcr.io/cozystack/cozystack/matchbox:v0.37.1@sha256:160c583a1c05ae06e304f7065dbf5ddad0bf9b59bf1a227f8a82f9d331d29c9d
|
||||
|
||||
@@ -1 +1 @@
|
||||
ghcr.io/cozystack/cozystack/objectstorage-sidecar:v0.37.0@sha256:f166f09cdc9cdbb758209883819ab8261a3793bc1d7a6b6685efd5a2b2930847
|
||||
ghcr.io/cozystack/cozystack/objectstorage-sidecar:v0.37.1@sha256:f166f09cdc9cdbb758209883819ab8261a3793bc1d7a6b6685efd5a2b2930847
|
||||
|
||||
@@ -1 +1 @@
|
||||
ghcr.io/cozystack/cozystack/s3manager:v0.5.0@sha256:7348bec610f08bd902c88c9a9f28fdd644727e2728a1e4103f88f0c99febd5e7
|
||||
ghcr.io/cozystack/cozystack/s3manager:v0.5.0@sha256:26e241c285e3cf20c043545bf25517ec52f000a738b7ed9168656b58e59749a3
|
||||
|
||||
@@ -6,6 +6,9 @@ rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["namespaces", "secrets"]
|
||||
verbs: ["get", "watch", "list"]
|
||||
- apiGroups: ["rbac.authorization.k8s.io"]
|
||||
resources: ["rolebindings"]
|
||||
verbs: ["get", "watch", "list"]
|
||||
- apiGroups: [""]
|
||||
resources: ["secrets"]
|
||||
verbs: ["create", "update", "patch", "delete"]
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
cozystackAPI:
|
||||
image: ghcr.io/cozystack/cozystack/cozystack-api:v0.37.0@sha256:19d89e8afb90ce38ab7e42ecedfc28402f7c0b56f30957db957c5415132ff6ca
|
||||
image: ghcr.io/cozystack/cozystack/cozystack-api:v0.37.1@sha256:dc8f90f7c9551f1487670e512734939bf1585568fec04e74e4c5cac0bcabb1b9
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
cozystackController:
|
||||
image: ghcr.io/cozystack/cozystack/cozystack-controller:v0.37.0@sha256:845b8e68cbc277c2303080bcd55597e4334610d396dad258ad56fd906530acc3
|
||||
image: ghcr.io/cozystack/cozystack/cozystack-controller:v0.37.1@sha256:a78f8f0796a4b56a36a8f0abd3a502b61cf2745a50b9d54fdb2e13b3e691509b
|
||||
debug: false
|
||||
disableTelemetry: false
|
||||
cozystackVersion: "v0.37.0"
|
||||
cozystackVersion: "v0.37.1"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{{- $brandingConfig:= lookup "v1" "ConfigMap" "cozy-system" "cozystack-branding" }}
|
||||
|
||||
{{- $tenantText := "v0.37.0" }}
|
||||
{{- $tenantText := "v0.37.1" }}
|
||||
{{- $footerText := "Cozystack" }}
|
||||
{{- $titleText := "Cozystack Dashboard" }}
|
||||
{{- $logoText := "false" }}
|
||||
|
||||
@@ -55,6 +55,8 @@ spec:
|
||||
- --http-address=0.0.0.0:8000
|
||||
- --redirect-url=https://dashboard.{{ $host }}/oauth2/callback
|
||||
- --oidc-issuer-url=https://keycloak.{{ $host }}/realms/cozy
|
||||
- --backend-logout-url=https://keycloak.{{ $host }}/realms/cozy/protocol/openid-connect/logout?id_token_hint={id_token}
|
||||
- --whitelist-domain=keycloak.{{ $host }}
|
||||
- --email-domain=*
|
||||
- --pass-access-token=true
|
||||
- --pass-authorization-header=true
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
openapiUI:
|
||||
image: ghcr.io/cozystack/cozystack/openapi-ui:v0.37.0@sha256:13f38cf56830e899eb5e3d9dc8184965dd8dba9f8cd3c5ca10df0970355842d6
|
||||
image: ghcr.io/cozystack/cozystack/openapi-ui:v0.37.1@sha256:3fd556689816ac2a0a3af9c7a2e4025936f9fc716e57e9aabb8cc1b576819aae
|
||||
openapiUIK8sBff:
|
||||
image: ghcr.io/cozystack/cozystack/openapi-ui-k8s-bff:v0.37.0@sha256:2b626dbbf87241e8621ac5b0285f402edbc2c2069ba254ca2ace2dd5c9248ac8
|
||||
image: ghcr.io/cozystack/cozystack/openapi-ui-k8s-bff:v0.37.1@sha256:fe3f570adf35798c5a46bee0737975b6d8432eb5b0c0e2a6d529eb330c4a29f9
|
||||
tokenProxy:
|
||||
image: ghcr.io/cozystack/cozystack/token-proxy:v0.37.0@sha256:fad27112617bb17816702571e1f39d0ac3fe5283468d25eb12f79906cdab566b
|
||||
image: ghcr.io/cozystack/cozystack/token-proxy:v0.37.1@sha256:fad27112617bb17816702571e1f39d0ac3fe5283468d25eb12f79906cdab566b
|
||||
|
||||
@@ -3,7 +3,7 @@ kamaji:
|
||||
deploy: false
|
||||
image:
|
||||
pullPolicy: IfNotPresent
|
||||
tag: v0.37.0@sha256:9f4fd5045ede2909fbaf2572e4138fcbd8921071ecf8f08446257fddd0e6f655
|
||||
tag: v0.37.1@sha256:9f4fd5045ede2909fbaf2572e4138fcbd8921071ecf8f08446257fddd0e6f655
|
||||
repository: ghcr.io/cozystack/cozystack/kamaji
|
||||
resources:
|
||||
limits:
|
||||
@@ -13,4 +13,4 @@ kamaji:
|
||||
cpu: 100m
|
||||
memory: 100Mi
|
||||
extraArgs:
|
||||
- --migrate-image=ghcr.io/cozystack/cozystack/kamaji:v0.37.0@sha256:9f4fd5045ede2909fbaf2572e4138fcbd8921071ecf8f08446257fddd0e6f655
|
||||
- --migrate-image=ghcr.io/cozystack/cozystack/kamaji:v0.37.1@sha256:9f4fd5045ede2909fbaf2572e4138fcbd8921071ecf8f08446257fddd0e6f655
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
portSecurity: true
|
||||
routes: ""
|
||||
image: ghcr.io/cozystack/cozystack/kubeovn-plunger:v0.37.0@sha256:9950614571ea77a55925eba0839b6b12c8e5a7a30b8858031a8c6050f261af1a
|
||||
image: ghcr.io/cozystack/cozystack/kubeovn-plunger:v0.37.1@sha256:ec5794c58ec4f6a6041555c91ae2e8be01c21af4f34bb1940551b9e7ee0eaf6f
|
||||
ovnCentralName: ovn-central
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
portSecurity: true
|
||||
routes: ""
|
||||
image: ghcr.io/cozystack/cozystack/kubeovn-webhook:v0.37.0@sha256:7e63205708e607ce2cedfe2a2cafd323ca51e3ebc71244a21ff6f9016c6c87bc
|
||||
image: ghcr.io/cozystack/cozystack/kubeovn-webhook:v0.37.1@sha256:f803cf5e7a2f1fa2bcf7003f8a5931e5d7bccddce7f92c88029292b4826c9050
|
||||
|
||||
@@ -64,4 +64,4 @@ global:
|
||||
images:
|
||||
kubeovn:
|
||||
repository: kubeovn
|
||||
tag: v1.14.5@sha256:af10da442a0c6dc7df47a0ef752e2eb5c247bb0b43069fdfcb2aa51511185ea2
|
||||
tag: v1.14.5@sha256:f9b88f3276b84c892853b42ca06edfc4e8bf53399d902f993459add03cb51a54
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
objectstorage:
|
||||
controller:
|
||||
image: "ghcr.io/cozystack/cozystack/objectstorage-controller:v0.37.0@sha256:5f2eed05d19ba971806374834cb16ca49282aac76130194c00b213c79ce3e10d"
|
||||
image: "ghcr.io/cozystack/cozystack/objectstorage-controller:v0.37.1@sha256:5f2eed05d19ba971806374834cb16ca49282aac76130194c00b213c79ce3e10d"
|
||||
|
||||
@@ -120,7 +120,7 @@ seaweedfs:
|
||||
bucketClassName: "seaweedfs"
|
||||
region: ""
|
||||
sidecar:
|
||||
image: "ghcr.io/cozystack/cozystack/objectstorage-sidecar:v0.37.0@sha256:f166f09cdc9cdbb758209883819ab8261a3793bc1d7a6b6685efd5a2b2930847"
|
||||
image: "ghcr.io/cozystack/cozystack/objectstorage-sidecar:v0.37.1@sha256:f166f09cdc9cdbb758209883819ab8261a3793bc1d7a6b6685efd5a2b2930847"
|
||||
certificates:
|
||||
commonName: "SeaweedFS CA"
|
||||
ipAddresses: []
|
||||
|
||||
@@ -138,8 +138,7 @@ func (c completedConfig) New() (*CozyServer, error) {
|
||||
coreV1alpha1Storage["tenantnamespaces"] = cozyregistry.RESTInPeace(
|
||||
tenantnamespacestorage.NewREST(
|
||||
clientset.CoreV1(),
|
||||
clientset.AuthorizationV1(),
|
||||
20,
|
||||
clientset.RbacV1(),
|
||||
),
|
||||
)
|
||||
coreV1alpha1Storage["tenantsecrets"] = cozyregistry.RESTInPeace(
|
||||
|
||||
@@ -7,13 +7,10 @@ package tenantnamespace
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
authorizationv1 "k8s.io/api/authorization/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metainternal "k8s.io/apimachinery/pkg/apis/meta/internalversion"
|
||||
@@ -24,9 +21,8 @@ import (
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
authorizationv1client "k8s.io/client-go/kubernetes/typed/authorization/v1"
|
||||
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
"k8s.io/klog/v2"
|
||||
rbacv1client "k8s.io/client-go/kubernetes/typed/rbac/v1"
|
||||
|
||||
corev1alpha1 "github.com/cozystack/cozystack/pkg/apis/core/v1alpha1"
|
||||
)
|
||||
@@ -50,21 +46,18 @@ var (
|
||||
)
|
||||
|
||||
type REST struct {
|
||||
core corev1client.CoreV1Interface
|
||||
authClient authorizationv1client.AuthorizationV1Interface
|
||||
maxWorkers int
|
||||
gvr schema.GroupVersionResource
|
||||
core corev1client.CoreV1Interface
|
||||
rbac rbacv1client.RbacV1Interface
|
||||
gvr schema.GroupVersionResource
|
||||
}
|
||||
|
||||
func NewREST(
|
||||
coreCli corev1client.CoreV1Interface,
|
||||
authCli authorizationv1client.AuthorizationV1Interface,
|
||||
maxWorkers int,
|
||||
rbacCli rbacv1client.RbacV1Interface,
|
||||
) *REST {
|
||||
return &REST{
|
||||
core: coreCli,
|
||||
authClient: authCli,
|
||||
maxWorkers: maxWorkers,
|
||||
core: coreCli,
|
||||
rbac: rbacCli,
|
||||
gvr: schema.GroupVersionResource{
|
||||
Group: corev1alpha1.GroupName,
|
||||
Version: "v1alpha1",
|
||||
@@ -271,76 +264,53 @@ func (r *REST) filterAccessible(
|
||||
ctx context.Context,
|
||||
names []string,
|
||||
) ([]string, error) {
|
||||
workers := int(math.Min(float64(r.maxWorkers), float64(len(names))))
|
||||
type job struct{ name string }
|
||||
type res struct {
|
||||
name string
|
||||
allowed bool
|
||||
err error
|
||||
u, ok := request.UserFrom(ctx)
|
||||
if !ok {
|
||||
return []string{}, fmt.Errorf("user missing in context")
|
||||
}
|
||||
jobs := make(chan job, workers)
|
||||
out := make(chan res, workers)
|
||||
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < workers; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for j := range jobs {
|
||||
ok, err := r.sar(ctx, j.name)
|
||||
out <- res{j.name, ok, err}
|
||||
}
|
||||
}()
|
||||
groups := make(map[string]struct{})
|
||||
for _, group := range u.GetGroups() {
|
||||
groups[group] = struct{}{}
|
||||
}
|
||||
go func() { wg.Wait(); close(out) }()
|
||||
|
||||
go func() {
|
||||
for _, n := range names {
|
||||
jobs <- job{n}
|
||||
}
|
||||
close(jobs)
|
||||
}()
|
||||
|
||||
var allowed []string
|
||||
for r := range out {
|
||||
if r.err != nil {
|
||||
klog.Errorf("SAR failed for %s: %v", r.name, r.err)
|
||||
if _, ok = groups["system:masters"]; ok {
|
||||
return names, nil
|
||||
}
|
||||
if _, ok = groups["cozystack-cluster-admin"]; ok {
|
||||
return names, nil
|
||||
}
|
||||
nameSet := make(map[string]struct{})
|
||||
for _, name := range names {
|
||||
nameSet[name] = struct{}{}
|
||||
}
|
||||
rbs, err := r.rbac.RoleBindings("").List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return []string{}, fmt.Errorf("failed to list rolebindings")
|
||||
}
|
||||
allowedNameSet := make(map[string]struct{})
|
||||
for i := range rbs.Items {
|
||||
if _, ok := allowedNameSet[rbs.Items[i].Namespace]; ok {
|
||||
continue
|
||||
}
|
||||
if r.allowed {
|
||||
allowed = append(allowed, r.name)
|
||||
if _, ok := nameSet[rbs.Items[i].Namespace]; !ok {
|
||||
continue
|
||||
}
|
||||
for j := range rbs.Items[i].Subjects {
|
||||
if rbs.Items[i].Subjects[j].Kind != "Group" {
|
||||
continue
|
||||
}
|
||||
if _, ok = groups[rbs.Items[i].Subjects[j].Name]; ok {
|
||||
allowedNameSet[rbs.Items[i].Namespace] = struct{}{}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
allowed := make([]string, 0, len(allowedNameSet))
|
||||
for name := range allowedNameSet {
|
||||
allowed = append(allowed, name)
|
||||
}
|
||||
return allowed, nil
|
||||
}
|
||||
|
||||
func (r *REST) sar(ctx context.Context, ns string) (bool, error) {
|
||||
u, ok := request.UserFrom(ctx)
|
||||
if !ok || u == nil {
|
||||
return false, fmt.Errorf("user missing in context")
|
||||
}
|
||||
|
||||
sar := &authorizationv1.SubjectAccessReview{
|
||||
Spec: authorizationv1.SubjectAccessReviewSpec{
|
||||
User: u.GetName(),
|
||||
Groups: u.GetGroups(),
|
||||
ResourceAttributes: &authorizationv1.ResourceAttributes{
|
||||
Group: "cozystack.io",
|
||||
Resource: "workloadmonitors",
|
||||
Verb: "get",
|
||||
Namespace: ns,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
rsp, err := r.authClient.SubjectAccessReviews().
|
||||
Create(ctx, sar, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return rsp.Status.Allowed, nil
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Boiler-plate
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
@@ -28,6 +28,8 @@ cozypkg -n cozy-system -C packages/system/cozystack-api apply cozystack-api --pl
|
||||
helm upgrade --install -n cozy-system cozystack-controller ./packages/system/cozystack-controller/ --take-ownership
|
||||
|
||||
sleep 5
|
||||
timeout 60 sh -c 'until kubectl create service clusterip lineage-webhook-test --clusterip="None" --dry-run=server; do sleep 1; done'
|
||||
|
||||
kubectl wait deployment/cozystack-api -n cozy-system --timeout=4m --for=condition=available || exit 1
|
||||
kubectl wait deployment/cozystack-controller -n cozy-system --timeout=4m --for=condition=available || exit 1
|
||||
|
||||
|
||||
Reference in New Issue
Block a user