mirror of
https://github.com/gravitational/teleport.git
synced 2026-09-19 10:10:29 +08:00
Pass k8s api group around. (#54760)
* Pass the api group around. Set the default value as wildcard. No behavior/logic change. * Revert presets back to v7 to pass the merge queue tests.
This commit is contained in:
@@ -1593,7 +1593,7 @@ protos-up-to-date/host: must-start-clean/host grpc/host
|
||||
.PHONY: must-start-clean/host
|
||||
must-start-clean/host:
|
||||
@if ! git diff --quiet; then \
|
||||
@echo 'This must be run from a repo with no unstaged commits.'; \
|
||||
echo 'This must be run from a repo with no unstaged commits.'; \
|
||||
git diff; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
@@ -1196,6 +1196,7 @@ func (r *RoleV6) CheckAndSetDefaults() error {
|
||||
Namespace: Wildcard,
|
||||
Name: Wildcard,
|
||||
Verbs: []string{Wildcard},
|
||||
APIGroup: Wildcard,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,6 +197,7 @@ func withFullKubeAccessUserRole(t *testing.T) testOptionsFunc {
|
||||
Name: types.Wildcard,
|
||||
Namespace: types.Wildcard,
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
+18
-3
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"access": {
|
||||
"kind": "role",
|
||||
"version": "v8",
|
||||
"version": "v7",
|
||||
"metadata": {
|
||||
"name": "access",
|
||||
"description": "Access cluster resources",
|
||||
@@ -25,6 +25,11 @@
|
||||
"desktop_directory_sharing": true,
|
||||
"pin_source_ip": false,
|
||||
"ssh_file_copy": true,
|
||||
"idp": {
|
||||
"saml": {
|
||||
"enabled": true
|
||||
}
|
||||
},
|
||||
"create_desktop_user": false,
|
||||
"create_db_user": false,
|
||||
"ssh_port_forwarding": {
|
||||
@@ -147,7 +152,7 @@
|
||||
},
|
||||
"auditor": {
|
||||
"kind": "role",
|
||||
"version": "v8",
|
||||
"version": "v7",
|
||||
"metadata": {
|
||||
"name": "auditor",
|
||||
"description": "Review cluster events and replay sessions",
|
||||
@@ -171,6 +176,11 @@
|
||||
"desktop_directory_sharing": true,
|
||||
"pin_source_ip": false,
|
||||
"ssh_file_copy": true,
|
||||
"idp": {
|
||||
"saml": {
|
||||
"enabled": true
|
||||
}
|
||||
},
|
||||
"create_desktop_user": false,
|
||||
"create_db_user": false
|
||||
},
|
||||
@@ -266,7 +276,7 @@
|
||||
},
|
||||
"editor": {
|
||||
"kind": "role",
|
||||
"version": "v8",
|
||||
"version": "v7",
|
||||
"metadata": {
|
||||
"name": "editor",
|
||||
"description": "Edit cluster configuration",
|
||||
@@ -290,6 +300,11 @@
|
||||
"desktop_directory_sharing": true,
|
||||
"pin_source_ip": false,
|
||||
"ssh_file_copy": true,
|
||||
"idp": {
|
||||
"saml": {
|
||||
"enabled": true
|
||||
}
|
||||
},
|
||||
"create_desktop_user": false,
|
||||
"create_db_user": false,
|
||||
"ssh_port_forwarding": {
|
||||
|
||||
@@ -222,7 +222,7 @@ func testExec(t *testing.T, suite *KubeSuite, pinnedIP string, clientError strin
|
||||
},
|
||||
KubernetesResources: []types.KubernetesResource{
|
||||
{
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard},
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard}, APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -433,7 +433,7 @@ func testKubeDeny(t *testing.T, suite *KubeSuite) {
|
||||
KubeUsers: kubeUsers,
|
||||
KubernetesResources: []types.KubernetesResource{
|
||||
{
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard},
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard}, APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -491,7 +491,7 @@ func testKubePortForward(t *testing.T, suite *KubeSuite) {
|
||||
},
|
||||
KubernetesResources: []types.KubernetesResource{
|
||||
{
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard},
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard}, APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -621,7 +621,7 @@ func testKubeTrustedClustersClientCert(t *testing.T, suite *KubeSuite) {
|
||||
},
|
||||
KubernetesResources: []types.KubernetesResource{
|
||||
{
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard},
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard}, APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -667,7 +667,7 @@ func testKubeTrustedClustersClientCert(t *testing.T, suite *KubeSuite) {
|
||||
},
|
||||
KubernetesResources: []types.KubernetesResource{
|
||||
{
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard},
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard}, APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -891,7 +891,7 @@ func testKubeTrustedClustersSNI(t *testing.T, suite *KubeSuite) {
|
||||
},
|
||||
KubernetesResources: []types.KubernetesResource{
|
||||
{
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard},
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard}, APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -941,7 +941,7 @@ func testKubeTrustedClustersSNI(t *testing.T, suite *KubeSuite) {
|
||||
KubeGroups: auxKubeGroups,
|
||||
KubernetesResources: []types.KubernetesResource{
|
||||
{
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard},
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard}, APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1191,7 +1191,7 @@ func runKubeDisconnectTest(t *testing.T, suite *KubeSuite, tc disconnectTestCase
|
||||
},
|
||||
KubernetesResources: []types.KubernetesResource{
|
||||
{
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard},
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard}, APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1290,7 +1290,7 @@ func testKubeTransportProtocol(t *testing.T, suite *KubeSuite) {
|
||||
},
|
||||
KubernetesResources: []types.KubernetesResource{
|
||||
{
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard},
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard}, APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1403,6 +1403,7 @@ func testKubeEphemeralContainers(t *testing.T, suite *KubeSuite) {
|
||||
Name: types.Wildcard,
|
||||
Namespace: types.Wildcard,
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1682,7 +1683,7 @@ func testKubeExecWeb(t *testing.T, suite *KubeSuite) {
|
||||
},
|
||||
KubernetesResources: []types.KubernetesResource{
|
||||
{
|
||||
Kind: types.Wildcard, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard},
|
||||
Kind: types.Wildcard, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard}, APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -2179,7 +2180,7 @@ func testKubeJoin(t *testing.T, suite *KubeSuite) {
|
||||
},
|
||||
KubernetesResources: []types.KubernetesResource{
|
||||
{
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard},
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard}, APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -2401,7 +2402,7 @@ func testKubeJoinWeb(t *testing.T, suite *KubeSuite) {
|
||||
},
|
||||
KubernetesResources: []types.KubernetesResource{
|
||||
{
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard},
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard}, APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -2696,7 +2697,7 @@ func testExecNoAuth(t *testing.T, suite *KubeSuite) {
|
||||
},
|
||||
KubernetesResources: []types.KubernetesResource{
|
||||
{
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard},
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard}, APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -2715,7 +2716,7 @@ func testExecNoAuth(t *testing.T, suite *KubeSuite) {
|
||||
},
|
||||
KubernetesResources: []types.KubernetesResource{
|
||||
{
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard},
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard}, APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
RequireSessionJoin: []*types.SessionRequirePolicy{
|
||||
|
||||
@@ -349,7 +349,7 @@ func TestALPNSNIProxyKube(t *testing.T) {
|
||||
KubeUsers: []string{k8User},
|
||||
KubernetesResources: []types.KubernetesResource{
|
||||
{
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard},
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard}, APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -427,7 +427,7 @@ func TestALPNSNIProxyKubeV2Leaf(t *testing.T) {
|
||||
KubeUsers: []string{k8User},
|
||||
KubernetesResources: []types.KubernetesResource{
|
||||
{
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard},
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard}, APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -544,7 +544,7 @@ func TestKubePROXYProtocol(t *testing.T) {
|
||||
KubeUsers: []string{k8User},
|
||||
KubernetesResources: []types.KubernetesResource{
|
||||
{
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard},
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard}, APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -726,7 +726,7 @@ func TestKubeIPPinning(t *testing.T) {
|
||||
KubeUsers: []string{k8User},
|
||||
KubernetesResources: []types.KubernetesResource{
|
||||
{
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard},
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard}, APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1791,7 +1791,7 @@ func TestALPNSNIProxyGRPCSecure(t *testing.T) {
|
||||
KubeUsers: []string{k8User},
|
||||
KubernetesResources: []types.KubernetesResource{
|
||||
{
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard},
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard}, APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -415,7 +415,7 @@ func TestTeletermKubeGateway(t *testing.T) {
|
||||
KubeUsers: []string{k8User},
|
||||
KubernetesResources: []types.KubernetesResource{
|
||||
{
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard},
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard}, APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -90,7 +90,7 @@ func TestListKubernetesResources(t *testing.T) {
|
||||
// override the role to allow access to all kube resources.
|
||||
r.SetKubeResources(
|
||||
types.Allow,
|
||||
[]types.KubernetesResource{{Kind: types.Wildcard, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard}}},
|
||||
[]types.KubernetesResource{{Kind: types.Wildcard, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard}, APIGroup: types.Wildcard}},
|
||||
)
|
||||
},
|
||||
},
|
||||
|
||||
@@ -338,7 +338,6 @@ current-context: foo
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
fwd := &Forwarder{
|
||||
|
||||
@@ -185,6 +185,7 @@ func (f *Forwarder) handleDeleteCollectionReq(req *http.Request, sess *clusterSe
|
||||
items, err := deleteResources(
|
||||
params,
|
||||
types.KindKubePod,
|
||||
sess.apiResource.apiGroup,
|
||||
slices.ToPointers(o.Items),
|
||||
func(ctx context.Context, client kubernetes.Interface, name, namespace string) error {
|
||||
return trace.Wrap(client.CoreV1().Pods(namespace).Delete(ctx, name, deleteOptions))
|
||||
@@ -198,6 +199,7 @@ func (f *Forwarder) handleDeleteCollectionReq(req *http.Request, sess *clusterSe
|
||||
items, err := deleteResources(
|
||||
params,
|
||||
types.KindKubeSecret,
|
||||
sess.apiResource.apiGroup,
|
||||
slices.ToPointers(o.Items),
|
||||
func(ctx context.Context, client kubernetes.Interface, name, namespace string) error {
|
||||
return trace.Wrap(client.CoreV1().Secrets(namespace).Delete(ctx, name, deleteOptions))
|
||||
@@ -211,6 +213,7 @@ func (f *Forwarder) handleDeleteCollectionReq(req *http.Request, sess *clusterSe
|
||||
items, err := deleteResources(
|
||||
params,
|
||||
types.KindKubeConfigmap,
|
||||
sess.apiResource.apiGroup,
|
||||
slices.ToPointers(o.Items),
|
||||
func(ctx context.Context, client kubernetes.Interface, name, namespace string) error {
|
||||
return trace.Wrap(client.CoreV1().ConfigMaps(namespace).Delete(ctx, name, deleteOptions))
|
||||
@@ -224,6 +227,7 @@ func (f *Forwarder) handleDeleteCollectionReq(req *http.Request, sess *clusterSe
|
||||
items, err := deleteResources(
|
||||
params,
|
||||
types.KindKubeNamespace,
|
||||
sess.apiResource.apiGroup,
|
||||
slices.ToPointers(o.Items),
|
||||
func(ctx context.Context, client kubernetes.Interface, name, _ string) error {
|
||||
return trace.Wrap(client.CoreV1().Namespaces().Delete(ctx, name, deleteOptions))
|
||||
@@ -237,6 +241,7 @@ func (f *Forwarder) handleDeleteCollectionReq(req *http.Request, sess *clusterSe
|
||||
items, err := deleteResources(
|
||||
params,
|
||||
types.KindKubeServiceAccount,
|
||||
sess.apiResource.apiGroup,
|
||||
slices.ToPointers(o.Items),
|
||||
func(ctx context.Context, client kubernetes.Interface, name, namespace string) error {
|
||||
return trace.Wrap(client.CoreV1().ServiceAccounts(namespace).Delete(ctx, name, deleteOptions))
|
||||
@@ -250,6 +255,7 @@ func (f *Forwarder) handleDeleteCollectionReq(req *http.Request, sess *clusterSe
|
||||
items, err := deleteResources(
|
||||
params,
|
||||
types.KindKubePersistentVolume,
|
||||
sess.apiResource.apiGroup,
|
||||
slices.ToPointers(o.Items),
|
||||
func(ctx context.Context, client kubernetes.Interface, name, _ string) error {
|
||||
return trace.Wrap(client.CoreV1().PersistentVolumes().Delete(ctx, name, deleteOptions))
|
||||
@@ -264,6 +270,7 @@ func (f *Forwarder) handleDeleteCollectionReq(req *http.Request, sess *clusterSe
|
||||
items, err := deleteResources(
|
||||
params,
|
||||
types.KindKubePersistentVolumeClaim,
|
||||
sess.apiResource.apiGroup,
|
||||
slices.ToPointers(o.Items),
|
||||
func(ctx context.Context, client kubernetes.Interface, name, namespace string) error {
|
||||
return trace.Wrap(client.CoreV1().PersistentVolumeClaims(namespace).Delete(ctx, name, deleteOptions))
|
||||
@@ -277,6 +284,7 @@ func (f *Forwarder) handleDeleteCollectionReq(req *http.Request, sess *clusterSe
|
||||
items, err := deleteResources(
|
||||
params,
|
||||
types.KindKubeDeployment,
|
||||
sess.apiResource.apiGroup,
|
||||
slices.ToPointers(o.Items),
|
||||
func(ctx context.Context, client kubernetes.Interface, name, namespace string) error {
|
||||
return trace.Wrap(client.AppsV1().Deployments(namespace).Delete(ctx, name, deleteOptions))
|
||||
@@ -290,6 +298,7 @@ func (f *Forwarder) handleDeleteCollectionReq(req *http.Request, sess *clusterSe
|
||||
items, err := deleteResources(
|
||||
params,
|
||||
types.KindKubeReplicaSet,
|
||||
sess.apiResource.apiGroup,
|
||||
slices.ToPointers(o.Items),
|
||||
func(ctx context.Context, client kubernetes.Interface, name, namespace string) error {
|
||||
return trace.Wrap(client.AppsV1().ReplicaSets(namespace).Delete(ctx, name, deleteOptions))
|
||||
@@ -304,6 +313,7 @@ func (f *Forwarder) handleDeleteCollectionReq(req *http.Request, sess *clusterSe
|
||||
items, err := deleteResources(
|
||||
params,
|
||||
types.KindKubeStatefulset,
|
||||
sess.apiResource.apiGroup,
|
||||
slices.ToPointers(o.Items),
|
||||
func(ctx context.Context, client kubernetes.Interface, name, namespace string) error {
|
||||
return trace.Wrap(client.AppsV1().StatefulSets(namespace).Delete(ctx, name, deleteOptions))
|
||||
@@ -317,6 +327,7 @@ func (f *Forwarder) handleDeleteCollectionReq(req *http.Request, sess *clusterSe
|
||||
items, err := deleteResources(
|
||||
params,
|
||||
types.KindKubeDaemonSet,
|
||||
sess.apiResource.apiGroup,
|
||||
slices.ToPointers(o.Items),
|
||||
func(ctx context.Context, client kubernetes.Interface, name, namespace string) error {
|
||||
return trace.Wrap(client.AppsV1().DaemonSets(namespace).Delete(ctx, name, deleteOptions))
|
||||
@@ -331,6 +342,7 @@ func (f *Forwarder) handleDeleteCollectionReq(req *http.Request, sess *clusterSe
|
||||
items, err := deleteResources(
|
||||
params,
|
||||
types.KindKubeClusterRole,
|
||||
sess.apiResource.apiGroup,
|
||||
slices.ToPointers(o.Items),
|
||||
func(ctx context.Context, client kubernetes.Interface, name, _ string) error {
|
||||
return trace.Wrap(client.RbacV1().ClusterRoles().Delete(ctx, name, deleteOptions))
|
||||
@@ -344,6 +356,7 @@ func (f *Forwarder) handleDeleteCollectionReq(req *http.Request, sess *clusterSe
|
||||
items, err := deleteResources(
|
||||
params,
|
||||
types.KindKubeRole,
|
||||
sess.apiResource.apiGroup,
|
||||
slices.ToPointers(o.Items),
|
||||
func(ctx context.Context, client kubernetes.Interface, name, namespace string) error {
|
||||
return trace.Wrap(client.RbacV1().Roles(namespace).Delete(ctx, name, deleteOptions))
|
||||
@@ -357,6 +370,7 @@ func (f *Forwarder) handleDeleteCollectionReq(req *http.Request, sess *clusterSe
|
||||
items, err := deleteResources(
|
||||
params,
|
||||
types.KindKubeClusterRoleBinding,
|
||||
sess.apiResource.apiGroup,
|
||||
slices.ToPointers(o.Items),
|
||||
func(ctx context.Context, client kubernetes.Interface, name, _ string) error {
|
||||
return trace.Wrap(client.RbacV1().ClusterRoleBindings().Delete(ctx, name, deleteOptions))
|
||||
@@ -370,6 +384,7 @@ func (f *Forwarder) handleDeleteCollectionReq(req *http.Request, sess *clusterSe
|
||||
items, err := deleteResources(
|
||||
params,
|
||||
types.KindKubeRoleBinding,
|
||||
sess.apiResource.apiGroup,
|
||||
slices.ToPointers(o.Items),
|
||||
func(ctx context.Context, client kubernetes.Interface, name, namespace string) error {
|
||||
return trace.Wrap(client.RbacV1().RoleBindings(namespace).Delete(ctx, name, deleteOptions))
|
||||
@@ -383,6 +398,7 @@ func (f *Forwarder) handleDeleteCollectionReq(req *http.Request, sess *clusterSe
|
||||
items, err := deleteResources(
|
||||
params,
|
||||
types.KindKubeCronjob,
|
||||
sess.apiResource.apiGroup,
|
||||
slices.ToPointers(o.Items),
|
||||
func(ctx context.Context, client kubernetes.Interface, name, namespace string) error {
|
||||
return trace.Wrap(client.BatchV1().CronJobs(namespace).Delete(ctx, name, deleteOptions))
|
||||
@@ -396,6 +412,7 @@ func (f *Forwarder) handleDeleteCollectionReq(req *http.Request, sess *clusterSe
|
||||
items, err := deleteResources(
|
||||
params,
|
||||
types.KindKubeJob,
|
||||
sess.apiResource.apiGroup,
|
||||
slices.ToPointers(o.Items),
|
||||
func(ctx context.Context, client kubernetes.Interface, name, namespace string) error {
|
||||
return trace.Wrap(client.BatchV1().Jobs(namespace).Delete(ctx, name, deleteOptions))
|
||||
@@ -409,6 +426,7 @@ func (f *Forwarder) handleDeleteCollectionReq(req *http.Request, sess *clusterSe
|
||||
items, err := deleteResources(
|
||||
params,
|
||||
types.KindKubeCertificateSigningRequest,
|
||||
sess.apiResource.apiGroup,
|
||||
slices.ToPointers(o.Items),
|
||||
func(ctx context.Context, client kubernetes.Interface, name, _ string) error {
|
||||
return trace.Wrap(client.CertificatesV1().CertificateSigningRequests().Delete(ctx, name, deleteOptions))
|
||||
@@ -422,6 +440,7 @@ func (f *Forwarder) handleDeleteCollectionReq(req *http.Request, sess *clusterSe
|
||||
items, err := deleteResources(
|
||||
params,
|
||||
types.KindKubeIngress,
|
||||
sess.apiResource.apiGroup,
|
||||
slices.ToPointers(o.Items),
|
||||
func(ctx context.Context, client kubernetes.Interface, name, namespace string) error {
|
||||
return trace.Wrap(client.NetworkingV1().Ingresses(namespace).Delete(ctx, name, deleteOptions))
|
||||
@@ -435,6 +454,7 @@ func (f *Forwarder) handleDeleteCollectionReq(req *http.Request, sess *clusterSe
|
||||
items, err := deleteResources(
|
||||
params,
|
||||
types.KindKubeIngress,
|
||||
sess.apiResource.apiGroup,
|
||||
slices.ToPointers(o.Items),
|
||||
func(ctx context.Context, client kubernetes.Interface, name, namespace string) error {
|
||||
return trace.Wrap(client.ExtensionsV1beta1().Ingresses(namespace).Delete(ctx, name, deleteOptions))
|
||||
@@ -448,6 +468,7 @@ func (f *Forwarder) handleDeleteCollectionReq(req *http.Request, sess *clusterSe
|
||||
items, err := deleteResources(
|
||||
params,
|
||||
types.KindKubeDaemonSet,
|
||||
sess.apiResource.apiGroup,
|
||||
slices.ToPointers(o.Items),
|
||||
func(ctx context.Context, client kubernetes.Interface, name, namespace string) error {
|
||||
return trace.Wrap(client.ExtensionsV1beta1().DaemonSets(namespace).Delete(ctx, name, deleteOptions))
|
||||
@@ -461,6 +482,7 @@ func (f *Forwarder) handleDeleteCollectionReq(req *http.Request, sess *clusterSe
|
||||
items, err := deleteResources(
|
||||
params,
|
||||
types.KindKubeDeployment,
|
||||
sess.apiResource.apiGroup,
|
||||
slices.ToPointers(o.Items),
|
||||
func(ctx context.Context, client kubernetes.Interface, name, namespace string) error {
|
||||
return trace.Wrap(client.ExtensionsV1beta1().Deployments(namespace).Delete(ctx, name, deleteOptions))
|
||||
@@ -474,6 +496,7 @@ func (f *Forwarder) handleDeleteCollectionReq(req *http.Request, sess *clusterSe
|
||||
items, err := deleteResources(
|
||||
params,
|
||||
types.KindKubeReplicaSet,
|
||||
sess.apiResource.apiGroup,
|
||||
slices.ToPointers(o.Items),
|
||||
func(ctx context.Context, client kubernetes.Interface, name, namespace string) error {
|
||||
return trace.Wrap(client.ExtensionsV1beta1().ReplicaSets(namespace).Delete(ctx, name, deleteOptions))
|
||||
@@ -591,7 +614,7 @@ type deleteResourcesCommonParams struct {
|
||||
|
||||
func deleteResources[T kubeObjectInterface](
|
||||
params deleteResourcesCommonParams,
|
||||
kind string,
|
||||
kind, group string,
|
||||
items []T,
|
||||
deleteOP func(ctx context.Context, client kubernetes.Interface, name, namespace string) error,
|
||||
) ([]T, error) {
|
||||
@@ -607,7 +630,7 @@ func deleteResources[T kubeObjectInterface](
|
||||
params.authCtx.Checker.Traits(),
|
||||
),
|
||||
services.NewKubernetesResourceMatcher(
|
||||
getKubeResource(kind, types.KubeVerbDeleteCollection, item),
|
||||
getKubeResource(kind, group, types.KubeVerbDeleteCollection, item),
|
||||
),
|
||||
)
|
||||
// no match was found, we ignore the request.
|
||||
|
||||
@@ -52,7 +52,7 @@ import (
|
||||
// - deniedResources: excluded if (namespace,name) matches an entry even if it matches
|
||||
// the allowedResources's list.
|
||||
// - allowedResources: excluded if (namespace,name) not match a single entry.
|
||||
func newResourceFilterer(kind, verb string, codecs *serializer.CodecFactory, allowedResources, deniedResources []types.KubernetesResource, log *slog.Logger) responsewriters.FilterWrapper {
|
||||
func newResourceFilterer(kind, group, verb string, codecs *serializer.CodecFactory, allowedResources, deniedResources []types.KubernetesResource, log *slog.Logger) responsewriters.FilterWrapper {
|
||||
// If the list of allowed resources contains a wildcard and no deniedResources, then we
|
||||
// don't need to filter anything.
|
||||
if containsWildcard(allowedResources) && len(deniedResources) == 0 {
|
||||
@@ -74,6 +74,7 @@ func newResourceFilterer(kind, verb string, codecs *serializer.CodecFactory, all
|
||||
deniedResources: deniedResources,
|
||||
log: log,
|
||||
kind: kind,
|
||||
group: group,
|
||||
verb: verb,
|
||||
}, nil
|
||||
}
|
||||
@@ -118,6 +119,8 @@ type resourceFilterer struct {
|
||||
log *slog.Logger
|
||||
// kind is the type of the resource.
|
||||
kind string
|
||||
// group is the api group of the resource.
|
||||
group string
|
||||
// verb is the kube API verb based on HTTP verb.
|
||||
verb string
|
||||
}
|
||||
@@ -167,7 +170,7 @@ func (d *resourceFilterer) FilterObj(obj runtime.Object) (isAllowed bool, isList
|
||||
// should be forwarded to the user.
|
||||
return true, false, nil
|
||||
case *corev1.Pod:
|
||||
result, err := filterResource(d.kind, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
result, err := filterResource(d.kind, d.group, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
if err != nil {
|
||||
d.log.WarnContext(ctx, "Unable to compile regex expressions within kubernetes_resources", "error", err)
|
||||
}
|
||||
@@ -176,12 +179,12 @@ func (d *resourceFilterer) FilterObj(obj runtime.Object) (isAllowed bool, isList
|
||||
case *corev1.PodList:
|
||||
o.Items = slices.FromPointers(
|
||||
filterResourceList(
|
||||
d.kind, d.verb,
|
||||
d.kind, d.group, d.verb,
|
||||
slices.ToPointers(o.Items), d.allowedResources, d.deniedResources, d.log),
|
||||
)
|
||||
return len(o.Items) > 0, true, nil
|
||||
case *corev1.Secret:
|
||||
result, err := filterResource(d.kind, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
result, err := filterResource(d.kind, d.group, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
if err != nil {
|
||||
d.log.WarnContext(ctx, "Unable to compile regex expressions within kubernetes_resources", "error", err)
|
||||
}
|
||||
@@ -190,12 +193,12 @@ func (d *resourceFilterer) FilterObj(obj runtime.Object) (isAllowed bool, isList
|
||||
case *corev1.SecretList:
|
||||
o.Items = slices.FromPointers(
|
||||
filterResourceList(
|
||||
d.kind, d.verb,
|
||||
d.kind, d.group, d.verb,
|
||||
slices.ToPointers(o.Items), d.allowedResources, d.deniedResources, d.log),
|
||||
)
|
||||
return len(o.Items) > 0, true, nil
|
||||
case *corev1.ConfigMap:
|
||||
result, err := filterResource(d.kind, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
result, err := filterResource(d.kind, d.group, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
if err != nil {
|
||||
d.log.WarnContext(ctx, "Unable to compile regex expressions within kubernetes_resources", "error", err)
|
||||
}
|
||||
@@ -204,12 +207,12 @@ func (d *resourceFilterer) FilterObj(obj runtime.Object) (isAllowed bool, isList
|
||||
case *corev1.ConfigMapList:
|
||||
o.Items = slices.FromPointers(
|
||||
filterResourceList(
|
||||
d.kind, d.verb,
|
||||
d.kind, d.group, d.verb,
|
||||
slices.ToPointers(o.Items), d.allowedResources, d.deniedResources, d.log),
|
||||
)
|
||||
return len(o.Items) > 0, true, nil
|
||||
case *corev1.Namespace:
|
||||
result, err := filterResource(d.kind, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
result, err := filterResource(d.kind, d.group, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
if err != nil {
|
||||
d.log.WarnContext(ctx, "Unable to compile regex expressions within kubernetes_resources", "error", err)
|
||||
}
|
||||
@@ -218,12 +221,12 @@ func (d *resourceFilterer) FilterObj(obj runtime.Object) (isAllowed bool, isList
|
||||
case *corev1.NamespaceList:
|
||||
o.Items = slices.FromPointers(
|
||||
filterResourceList(
|
||||
d.kind, d.verb,
|
||||
d.kind, d.group, d.verb,
|
||||
slices.ToPointers(o.Items), d.allowedResources, d.deniedResources, d.log),
|
||||
)
|
||||
return len(o.Items) > 0, true, nil
|
||||
case *corev1.Service:
|
||||
result, err := filterResource(d.kind, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
result, err := filterResource(d.kind, d.group, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
if err != nil {
|
||||
d.log.WarnContext(ctx, "Unable to compile regex expressions within kubernetes_resources", "error", err)
|
||||
}
|
||||
@@ -232,12 +235,12 @@ func (d *resourceFilterer) FilterObj(obj runtime.Object) (isAllowed bool, isList
|
||||
case *corev1.ServiceList:
|
||||
o.Items = slices.FromPointers(
|
||||
filterResourceList(
|
||||
d.kind, d.verb,
|
||||
d.kind, d.group, d.verb,
|
||||
slices.ToPointers(o.Items), d.allowedResources, d.deniedResources, d.log),
|
||||
)
|
||||
return len(o.Items) > 0, true, nil
|
||||
case *corev1.Endpoints: //nolint:staticcheck // SA1019. Rreserve compatibility until RBAC is tweaked to support discovery endpoints.
|
||||
result, err := filterResource(d.kind, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
case *corev1.Endpoints: //nolint:staticcheck // SA1019. Preserve compatibility until RBAC is tweaked to support discovery endpoints.
|
||||
result, err := filterResource(d.kind, d.group, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
if err != nil {
|
||||
d.log.WarnContext(ctx, "Unable to compile regex expressions within kubernetes_resources", "error", err)
|
||||
}
|
||||
@@ -246,12 +249,12 @@ func (d *resourceFilterer) FilterObj(obj runtime.Object) (isAllowed bool, isList
|
||||
case *corev1.EndpointsList:
|
||||
o.Items = slices.FromPointers(
|
||||
filterResourceList(
|
||||
d.kind, d.verb,
|
||||
d.kind, d.group, d.verb,
|
||||
slices.ToPointers(o.Items), d.allowedResources, d.deniedResources, d.log),
|
||||
)
|
||||
return len(o.Items) > 0, true, nil
|
||||
case *corev1.ServiceAccount:
|
||||
result, err := filterResource(d.kind, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
result, err := filterResource(d.kind, d.group, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
if err != nil {
|
||||
d.log.WarnContext(ctx, "Unable to compile regex expressions within kubernetes_resources", "error", err)
|
||||
}
|
||||
@@ -260,12 +263,12 @@ func (d *resourceFilterer) FilterObj(obj runtime.Object) (isAllowed bool, isList
|
||||
case *corev1.ServiceAccountList:
|
||||
o.Items = slices.FromPointers(
|
||||
filterResourceList(
|
||||
d.kind, d.verb,
|
||||
d.kind, d.group, d.verb,
|
||||
slices.ToPointers(o.Items), d.allowedResources, d.deniedResources, d.log),
|
||||
)
|
||||
return len(o.Items) > 0, true, nil
|
||||
case *corev1.Node:
|
||||
result, err := filterResource(d.kind, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
result, err := filterResource(d.kind, d.group, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
if err != nil {
|
||||
d.log.WarnContext(ctx, "Unable to compile regex expressions within kubernetes_resources", "error", err)
|
||||
}
|
||||
@@ -274,12 +277,12 @@ func (d *resourceFilterer) FilterObj(obj runtime.Object) (isAllowed bool, isList
|
||||
case *corev1.NodeList:
|
||||
o.Items = slices.FromPointers(
|
||||
filterResourceList(
|
||||
d.kind, d.verb,
|
||||
d.kind, d.group, d.verb,
|
||||
slices.ToPointers(o.Items), d.allowedResources, d.deniedResources, d.log),
|
||||
)
|
||||
return len(o.Items) > 0, true, nil
|
||||
case *corev1.PersistentVolume:
|
||||
result, err := filterResource(d.kind, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
result, err := filterResource(d.kind, d.group, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
if err != nil {
|
||||
d.log.WarnContext(ctx, "Unable to compile regex expressions within kubernetes_resources", "error", err)
|
||||
}
|
||||
@@ -288,12 +291,12 @@ func (d *resourceFilterer) FilterObj(obj runtime.Object) (isAllowed bool, isList
|
||||
case *corev1.PersistentVolumeList:
|
||||
o.Items = slices.FromPointers(
|
||||
filterResourceList(
|
||||
d.kind, d.verb,
|
||||
d.kind, d.group, d.verb,
|
||||
slices.ToPointers(o.Items), d.allowedResources, d.deniedResources, d.log),
|
||||
)
|
||||
return len(o.Items) > 0, true, nil
|
||||
case *corev1.PersistentVolumeClaim:
|
||||
result, err := filterResource(d.kind, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
result, err := filterResource(d.kind, d.group, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
if err != nil {
|
||||
d.log.WarnContext(ctx, "Unable to compile regex expressions within kubernetes_resources", "error", err)
|
||||
}
|
||||
@@ -302,13 +305,13 @@ func (d *resourceFilterer) FilterObj(obj runtime.Object) (isAllowed bool, isList
|
||||
case *corev1.PersistentVolumeClaimList:
|
||||
o.Items = slices.FromPointers(
|
||||
filterResourceList(
|
||||
d.kind, d.verb,
|
||||
d.kind, d.group, d.verb,
|
||||
slices.ToPointers(o.Items), d.allowedResources, d.deniedResources, d.log),
|
||||
)
|
||||
return len(o.Items) > 0, true, nil
|
||||
|
||||
case *appsv1.Deployment:
|
||||
result, err := filterResource(d.kind, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
result, err := filterResource(d.kind, d.group, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
if err != nil {
|
||||
d.log.WarnContext(ctx, "Unable to compile regex expressions within kubernetes_resources", "error", err)
|
||||
}
|
||||
@@ -317,13 +320,13 @@ func (d *resourceFilterer) FilterObj(obj runtime.Object) (isAllowed bool, isList
|
||||
case *appsv1.DeploymentList:
|
||||
o.Items = slices.FromPointers(
|
||||
filterResourceList(
|
||||
d.kind, d.verb,
|
||||
d.kind, d.group, d.verb,
|
||||
slices.ToPointers(o.Items), d.allowedResources, d.deniedResources, d.log),
|
||||
)
|
||||
return len(o.Items) > 0, true, nil
|
||||
|
||||
case *appsv1.ReplicaSet:
|
||||
result, err := filterResource(d.kind, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
result, err := filterResource(d.kind, d.group, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
if err != nil {
|
||||
d.log.WarnContext(ctx, "Unable to compile regex expressions within kubernetes_resources", "error", err)
|
||||
}
|
||||
@@ -332,12 +335,12 @@ func (d *resourceFilterer) FilterObj(obj runtime.Object) (isAllowed bool, isList
|
||||
case *appsv1.ReplicaSetList:
|
||||
o.Items = slices.FromPointers(
|
||||
filterResourceList(
|
||||
d.kind, d.verb,
|
||||
d.kind, d.group, d.verb,
|
||||
slices.ToPointers(o.Items), d.allowedResources, d.deniedResources, d.log),
|
||||
)
|
||||
return len(o.Items) > 0, true, nil
|
||||
case *appsv1.StatefulSet:
|
||||
result, err := filterResource(d.kind, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
result, err := filterResource(d.kind, d.group, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
if err != nil {
|
||||
d.log.WarnContext(ctx, "Unable to compile regex expressions within kubernetes_resources", "error", err)
|
||||
}
|
||||
@@ -346,13 +349,13 @@ func (d *resourceFilterer) FilterObj(obj runtime.Object) (isAllowed bool, isList
|
||||
case *appsv1.StatefulSetList:
|
||||
o.Items = slices.FromPointers(
|
||||
filterResourceList(
|
||||
d.kind, d.verb,
|
||||
d.kind, d.group, d.verb,
|
||||
slices.ToPointers(o.Items), d.allowedResources, d.deniedResources, d.log),
|
||||
)
|
||||
return len(o.Items) > 0, true, nil
|
||||
|
||||
case *appsv1.DaemonSet:
|
||||
result, err := filterResource(d.kind, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
result, err := filterResource(d.kind, d.group, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
if err != nil {
|
||||
d.log.WarnContext(ctx, "Unable to compile regex expressions within kubernetes_resources", "error", err)
|
||||
}
|
||||
@@ -361,12 +364,12 @@ func (d *resourceFilterer) FilterObj(obj runtime.Object) (isAllowed bool, isList
|
||||
case *appsv1.DaemonSetList:
|
||||
o.Items = slices.FromPointers(
|
||||
filterResourceList(
|
||||
d.kind, d.verb,
|
||||
d.kind, d.group, d.verb,
|
||||
slices.ToPointers(o.Items), d.allowedResources, d.deniedResources, d.log),
|
||||
)
|
||||
return len(o.Items) > 0, true, nil
|
||||
case *authv1.ClusterRole:
|
||||
result, err := filterResource(d.kind, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
result, err := filterResource(d.kind, d.group, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
if err != nil {
|
||||
d.log.WarnContext(ctx, "Unable to compile regex expressions within kubernetes_resources", "error", err)
|
||||
}
|
||||
@@ -375,12 +378,12 @@ func (d *resourceFilterer) FilterObj(obj runtime.Object) (isAllowed bool, isList
|
||||
case *authv1.ClusterRoleList:
|
||||
o.Items = slices.FromPointers(
|
||||
filterResourceList(
|
||||
d.kind, d.verb,
|
||||
d.kind, d.group, d.verb,
|
||||
slices.ToPointers(o.Items), d.allowedResources, d.deniedResources, d.log),
|
||||
)
|
||||
return len(o.Items) > 0, true, nil
|
||||
case *authv1.Role:
|
||||
result, err := filterResource(d.kind, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
result, err := filterResource(d.kind, d.group, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
if err != nil {
|
||||
d.log.WarnContext(ctx, "Unable to compile regex expressions within kubernetes_resources", "error", err)
|
||||
}
|
||||
@@ -389,13 +392,13 @@ func (d *resourceFilterer) FilterObj(obj runtime.Object) (isAllowed bool, isList
|
||||
case *authv1.RoleList:
|
||||
o.Items = slices.FromPointers(
|
||||
filterResourceList(
|
||||
d.kind, d.verb,
|
||||
d.kind, d.group, d.verb,
|
||||
slices.ToPointers(o.Items), d.allowedResources, d.deniedResources, d.log),
|
||||
)
|
||||
return len(o.Items) > 0, true, nil
|
||||
|
||||
case *authv1.ClusterRoleBinding:
|
||||
result, err := filterResource(d.kind, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
result, err := filterResource(d.kind, d.group, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
if err != nil {
|
||||
d.log.WarnContext(ctx, "Unable to compile regex expressions within kubernetes_resources", "error", err)
|
||||
}
|
||||
@@ -404,13 +407,13 @@ func (d *resourceFilterer) FilterObj(obj runtime.Object) (isAllowed bool, isList
|
||||
case *authv1.ClusterRoleBindingList:
|
||||
o.Items = slices.FromPointers(
|
||||
filterResourceList(
|
||||
d.kind, d.verb,
|
||||
d.kind, d.group, d.verb,
|
||||
slices.ToPointers(o.Items), d.allowedResources, d.deniedResources, d.log),
|
||||
)
|
||||
return len(o.Items) > 0, true, nil
|
||||
|
||||
case *authv1.RoleBinding:
|
||||
result, err := filterResource(d.kind, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
result, err := filterResource(d.kind, d.group, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
if err != nil {
|
||||
d.log.WarnContext(ctx, "Unable to compile regex expressions within kubernetes_resources", "error", err)
|
||||
}
|
||||
@@ -419,13 +422,13 @@ func (d *resourceFilterer) FilterObj(obj runtime.Object) (isAllowed bool, isList
|
||||
case *authv1.RoleBindingList:
|
||||
o.Items = slices.FromPointers(
|
||||
filterResourceList(
|
||||
d.kind, d.verb,
|
||||
d.kind, d.group, d.verb,
|
||||
slices.ToPointers(o.Items), d.allowedResources, d.deniedResources, d.log),
|
||||
)
|
||||
return len(o.Items) > 0, true, nil
|
||||
|
||||
case *batchv1.CronJob:
|
||||
result, err := filterResource(d.kind, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
result, err := filterResource(d.kind, d.group, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
if err != nil {
|
||||
d.log.WarnContext(ctx, "Unable to compile regex expressions within kubernetes_resources", "error", err)
|
||||
}
|
||||
@@ -434,13 +437,13 @@ func (d *resourceFilterer) FilterObj(obj runtime.Object) (isAllowed bool, isList
|
||||
case *batchv1.CronJobList:
|
||||
o.Items = slices.FromPointers(
|
||||
filterResourceList(
|
||||
d.kind, d.verb,
|
||||
d.kind, d.group, d.verb,
|
||||
slices.ToPointers(o.Items), d.allowedResources, d.deniedResources, d.log),
|
||||
)
|
||||
return len(o.Items) > 0, true, nil
|
||||
|
||||
case *batchv1.Job:
|
||||
result, err := filterResource(d.kind, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
result, err := filterResource(d.kind, d.group, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
if err != nil {
|
||||
d.log.WarnContext(ctx, "Unable to compile regex expressions within kubernetes_resources", "error", err)
|
||||
}
|
||||
@@ -449,13 +452,13 @@ func (d *resourceFilterer) FilterObj(obj runtime.Object) (isAllowed bool, isList
|
||||
case *batchv1.JobList:
|
||||
o.Items = slices.FromPointers(
|
||||
filterResourceList(
|
||||
d.kind, d.verb,
|
||||
d.kind, d.group, d.verb,
|
||||
slices.ToPointers(o.Items), d.allowedResources, d.deniedResources, d.log),
|
||||
)
|
||||
return len(o.Items) > 0, true, nil
|
||||
|
||||
case *certificatesv1.CertificateSigningRequest:
|
||||
result, err := filterResource(d.kind, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
result, err := filterResource(d.kind, d.group, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
if err != nil {
|
||||
d.log.WarnContext(ctx, "Unable to compile regex expressions within kubernetes_resources", "error", err)
|
||||
}
|
||||
@@ -464,12 +467,12 @@ func (d *resourceFilterer) FilterObj(obj runtime.Object) (isAllowed bool, isList
|
||||
case *certificatesv1.CertificateSigningRequestList:
|
||||
o.Items = slices.FromPointers(
|
||||
filterResourceList(
|
||||
d.kind, d.verb,
|
||||
d.kind, d.group, d.verb,
|
||||
slices.ToPointers(o.Items), d.allowedResources, d.deniedResources, d.log),
|
||||
)
|
||||
return len(o.Items) > 0, true, nil
|
||||
case *networkingv1.Ingress:
|
||||
result, err := filterResource(d.kind, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
result, err := filterResource(d.kind, d.group, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
if err != nil {
|
||||
d.log.WarnContext(ctx, "Unable to compile regex expressions within kubernetes_resources", "error", err)
|
||||
}
|
||||
@@ -478,12 +481,12 @@ func (d *resourceFilterer) FilterObj(obj runtime.Object) (isAllowed bool, isList
|
||||
case *networkingv1.IngressList:
|
||||
o.Items = slices.FromPointers(
|
||||
filterResourceList(
|
||||
d.kind, d.verb,
|
||||
d.kind, d.group, d.verb,
|
||||
slices.ToPointers(o.Items), d.allowedResources, d.deniedResources, d.log),
|
||||
)
|
||||
return len(o.Items) > 0, true, nil
|
||||
case *extensionsv1beta1.Ingress:
|
||||
result, err := filterResource(d.kind, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
result, err := filterResource(d.kind, d.group, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
if err != nil {
|
||||
d.log.WarnContext(ctx, "Unable to compile regex expressions within kubernetes_resources", "error", err)
|
||||
}
|
||||
@@ -492,13 +495,13 @@ func (d *resourceFilterer) FilterObj(obj runtime.Object) (isAllowed bool, isList
|
||||
case *extensionsv1beta1.IngressList:
|
||||
o.Items = slices.FromPointers(
|
||||
filterResourceList(
|
||||
d.kind, d.verb,
|
||||
d.kind, d.group, d.verb,
|
||||
slices.ToPointers(o.Items), d.allowedResources, d.deniedResources, d.log),
|
||||
)
|
||||
return len(o.Items) > 0, true, nil
|
||||
|
||||
case *extensionsv1beta1.DaemonSet:
|
||||
result, err := filterResource(d.kind, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
result, err := filterResource(d.kind, d.group, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
if err != nil {
|
||||
d.log.WarnContext(ctx, "Unable to compile regex expressions within kubernetes_resources", "error", err)
|
||||
}
|
||||
@@ -507,13 +510,13 @@ func (d *resourceFilterer) FilterObj(obj runtime.Object) (isAllowed bool, isList
|
||||
case *extensionsv1beta1.DaemonSetList:
|
||||
o.Items = slices.FromPointers(
|
||||
filterResourceList(
|
||||
d.kind, d.verb,
|
||||
d.kind, d.group, d.verb,
|
||||
slices.ToPointers(o.Items), d.allowedResources, d.deniedResources, d.log),
|
||||
)
|
||||
return len(o.Items) > 0, true, nil
|
||||
|
||||
case *extensionsv1beta1.Deployment:
|
||||
result, err := filterResource(d.kind, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
result, err := filterResource(d.kind, d.group, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
if err != nil {
|
||||
d.log.WarnContext(ctx, "Unable to compile regex expressions within kubernetes_resources", "error", err)
|
||||
}
|
||||
@@ -522,13 +525,13 @@ func (d *resourceFilterer) FilterObj(obj runtime.Object) (isAllowed bool, isList
|
||||
case *extensionsv1beta1.DeploymentList:
|
||||
o.Items = slices.FromPointers(
|
||||
filterResourceList(
|
||||
d.kind, d.verb,
|
||||
d.kind, d.group, d.verb,
|
||||
slices.ToPointers(o.Items), d.allowedResources, d.deniedResources, d.log),
|
||||
)
|
||||
return len(o.Items) > 0, true, nil
|
||||
|
||||
case *extensionsv1beta1.ReplicaSet:
|
||||
result, err := filterResource(d.kind, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
result, err := filterResource(d.kind, d.group, d.verb, o, d.allowedResources, d.deniedResources)
|
||||
if err != nil {
|
||||
d.log.WarnContext(ctx, "Unable to compile regex expressions within kubernetes_resources", "error", err)
|
||||
}
|
||||
@@ -537,18 +540,18 @@ func (d *resourceFilterer) FilterObj(obj runtime.Object) (isAllowed bool, isList
|
||||
case *extensionsv1beta1.ReplicaSetList:
|
||||
o.Items = slices.FromPointers(
|
||||
filterResourceList(
|
||||
d.kind, d.verb,
|
||||
d.kind, d.group, d.verb,
|
||||
slices.ToPointers(o.Items), d.allowedResources, d.deniedResources, d.log),
|
||||
)
|
||||
return len(o.Items) > 0, true, nil
|
||||
|
||||
case *unstructured.Unstructured:
|
||||
if o.IsList() {
|
||||
hasElemts := filterUnstructuredList(d.verb, o, d.allowedResources, d.deniedResources, d.log)
|
||||
hasElemts := filterUnstructuredList(d.kind, d.group, d.verb, o, d.allowedResources, d.deniedResources, d.log)
|
||||
return hasElemts, true, nil
|
||||
}
|
||||
|
||||
r := getKubeResource(utils.KubeCustomResource, d.verb, o)
|
||||
r := getKubeResource(d.kind, d.group, d.verb, o)
|
||||
result, err := matchKubernetesResource(
|
||||
r,
|
||||
d.allowedResources, d.deniedResources,
|
||||
@@ -617,10 +620,10 @@ func (d *resourceFilterer) encode(obj runtime.Object, w io.Writer) error {
|
||||
}
|
||||
|
||||
// filterResourceList excludes resources the user should not have access to.
|
||||
func filterResourceList[T kubeObjectInterface](kind, verb string, originalList []T, allowed, denied []types.KubernetesResource, log *slog.Logger) []T {
|
||||
func filterResourceList[T kubeObjectInterface](kind, group, verb string, originalList []T, allowed, denied []types.KubernetesResource, log *slog.Logger) []T {
|
||||
filteredList := make([]T, 0, len(originalList))
|
||||
for _, resource := range originalList {
|
||||
if result, err := filterResource(kind, verb, resource, allowed, denied); err == nil && result {
|
||||
if result, err := filterResource(kind, group, verb, resource, allowed, denied); err == nil && result {
|
||||
filteredList = append(filteredList, resource)
|
||||
} else if err != nil {
|
||||
slog.WarnContext(context.Background(), "Unable to compile regex expressions within kubernetes_resources", "error", err)
|
||||
@@ -638,20 +641,21 @@ type kubeObjectInterface interface {
|
||||
}
|
||||
|
||||
// filterResource validates if the user should access the current resource.
|
||||
func filterResource(kind, verb string, resource kubeObjectInterface, allowed, denied []types.KubernetesResource) (bool, error) {
|
||||
func filterResource(kind, group, verb string, resource kubeObjectInterface, allowed, denied []types.KubernetesResource) (bool, error) {
|
||||
result, err := matchKubernetesResource(
|
||||
getKubeResource(kind, verb, resource),
|
||||
getKubeResource(kind, group, verb, resource),
|
||||
allowed, denied,
|
||||
)
|
||||
return result, trace.Wrap(err)
|
||||
}
|
||||
|
||||
func getKubeResource(kind, verb string, obj kubeObjectInterface) types.KubernetesResource {
|
||||
func getKubeResource(kind, group, verb string, obj kubeObjectInterface) types.KubernetesResource {
|
||||
return types.KubernetesResource{
|
||||
Kind: kind,
|
||||
Namespace: obj.GetNamespace(),
|
||||
Name: obj.GetName(),
|
||||
Verbs: []string{verb},
|
||||
APIGroup: group,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -664,7 +668,7 @@ func (d *resourceFilterer) filterMetaV1Table(table *metav1.Table, allowedResourc
|
||||
if err := d.decodePartialObjectMetadata(row); err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
resource, err := getKubeResourcePartialMetadataObject(d.kind, d.verb, row.Object.Object)
|
||||
resource, err := getKubeResourcePartialMetadataObject(d.kind, d.group, d.verb, row.Object.Object)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
@@ -680,7 +684,7 @@ func (d *resourceFilterer) filterMetaV1Table(table *metav1.Table, allowedResourc
|
||||
|
||||
// getKubeResourcePartialMetadataObject checks if obj satisfies namespaceNamer or namer interfaces
|
||||
// otherwise returns an error.
|
||||
func getKubeResourcePartialMetadataObject(kind, verb string, obj runtime.Object) (types.KubernetesResource, error) {
|
||||
func getKubeResourcePartialMetadataObject(kind, group, verb string, obj runtime.Object) (types.KubernetesResource, error) {
|
||||
type namer interface {
|
||||
GetName() string
|
||||
}
|
||||
@@ -695,12 +699,14 @@ func getKubeResourcePartialMetadataObject(kind, verb string, obj runtime.Object)
|
||||
Name: o.GetName(),
|
||||
Kind: kind,
|
||||
Verbs: []string{verb},
|
||||
APIGroup: group,
|
||||
}, nil
|
||||
case namer:
|
||||
return types.KubernetesResource{
|
||||
Name: o.GetName(),
|
||||
Kind: kind,
|
||||
Verbs: []string{verb},
|
||||
Name: o.GetName(),
|
||||
Kind: kind,
|
||||
Verbs: []string{verb},
|
||||
APIGroup: group,
|
||||
}, nil
|
||||
default:
|
||||
return types.KubernetesResource{}, trace.BadParameter("unexpected %T type", obj)
|
||||
@@ -784,7 +790,7 @@ func filterBuffer(filterWrapper responsewriters.FilterWrapper, src *responsewrit
|
||||
// filterUnstructuredList filters the unstructured list object to exclude resources
|
||||
// that the user must not have access to.
|
||||
// The filtered list is re-assigned to `obj.Object["items"]`.
|
||||
func filterUnstructuredList(verb string, obj *unstructured.Unstructured, allowed, denied []types.KubernetesResource, log *slog.Logger) (hasElems bool) {
|
||||
func filterUnstructuredList(kind, group, verb string, obj *unstructured.Unstructured, allowed, denied []types.KubernetesResource, log *slog.Logger) (hasElems bool) {
|
||||
const (
|
||||
itemsKey = "items"
|
||||
)
|
||||
@@ -800,7 +806,7 @@ func filterUnstructuredList(verb string, obj *unstructured.Unstructured, allowed
|
||||
|
||||
filteredList := make([]any, 0, len(objList.Items))
|
||||
for _, resource := range objList.Items {
|
||||
r := getKubeResource(utils.KubeCustomResource, verb, &resource)
|
||||
r := getKubeResource(utils.KubeCustomResource, group, verb, &resource)
|
||||
if result, err := matchKubernetesResource(
|
||||
r,
|
||||
allowed, denied,
|
||||
|
||||
@@ -155,6 +155,7 @@ func Test_filterBuffer(t *testing.T) {
|
||||
allowedResources := []types.KubernetesResource{
|
||||
{
|
||||
Kind: r,
|
||||
APIGroup: "*",
|
||||
Namespace: "default",
|
||||
Name: "*",
|
||||
Verbs: []string{types.KubeVerbList},
|
||||
@@ -175,7 +176,7 @@ func Test_filterBuffer(t *testing.T) {
|
||||
|
||||
buf, decompress := newMemoryResponseWriter(t, data.Bytes(), tt.args.contentEncoding)
|
||||
|
||||
err = filterBuffer(newResourceFilterer(r, types.KubeVerbList, &globalKubeCodecs, allowedResources, nil, utils.NewSlogLoggerForTests()), buf)
|
||||
err = filterBuffer(newResourceFilterer(r, "", types.KubeVerbList, &globalKubeCodecs, allowedResources, nil, utils.NewSlogLoggerForTests()), buf)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Decompress the buffer to compare the result.
|
||||
@@ -235,7 +236,7 @@ func Test_filterBuffer(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
resource, err := getKubeResourcePartialMetadataObject(r, "list", row.Object.Object)
|
||||
resource, err := getKubeResourcePartialMetadataObject(r, "", "list", row.Object.Object)
|
||||
require.NoError(t, err)
|
||||
resources = append(resources, resource.Namespace+"/"+resource.Name)
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ func (f *Forwarder) listResources(sess *clusterSession, w http.ResponseWriter, r
|
||||
status = rw.Status()
|
||||
} else {
|
||||
allowedResources, deniedResources := sess.Checker.GetKubeResources(sess.kubeCluster)
|
||||
shouldBeAllowed, err := matchListRequestShouldBeAllowed(sess, resourceKind, allowedResources, deniedResources)
|
||||
shouldBeAllowed, err := matchListRequestShouldBeAllowed(sess, resourceKind, sess.apiResource.apiGroup, allowedResources, deniedResources)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
@@ -123,7 +123,7 @@ func (f *Forwarder) listResourcesList(req *http.Request, w http.ResponseWriter,
|
||||
// filterBuffer filters the response to exclude resources the user doesn't have access to.
|
||||
// The filtered payload will be written into memBuffer again.
|
||||
if err := filterBuffer(
|
||||
newResourceFilterer(resourceKind, verb, sess.codecFactory, allowedResources, deniedResources, f.log),
|
||||
newResourceFilterer(resourceKind, sess.apiResource.apiGroup, verb, sess.codecFactory, allowedResources, deniedResources, f.log),
|
||||
memBuffer,
|
||||
); err != nil {
|
||||
return memBuffer.Status(), trace.Wrap(err)
|
||||
@@ -140,12 +140,14 @@ func (f *Forwarder) listResourcesList(req *http.Request, w http.ResponseWriter,
|
||||
// has no access and present then a more user-friendly error message instead of returning
|
||||
// an empty list.
|
||||
// This function is not responsible for enforcing access rules.
|
||||
func matchListRequestShouldBeAllowed(sess *clusterSession, resourceKind string, allowedResources, deniedResources []types.KubernetesResource) (bool, error) {
|
||||
func matchListRequestShouldBeAllowed(sess *clusterSession, resourceKind, resourceGroup string, allowedResources, deniedResources []types.KubernetesResource) (bool, error) {
|
||||
resource := types.KubernetesResource{
|
||||
Kind: resourceKind,
|
||||
Namespace: sess.apiResource.namespace,
|
||||
Verbs: []string{sess.requestVerb},
|
||||
APIGroup: resourceGroup,
|
||||
}
|
||||
|
||||
result, err := utils.KubeResourceCouldMatchRules(resource, deniedResources, types.Deny)
|
||||
if err != nil {
|
||||
return false, trace.Wrap(err)
|
||||
@@ -182,6 +184,7 @@ func (f *Forwarder) listResourcesWatcher(req *http.Request, w http.ResponseWrite
|
||||
negotiator,
|
||||
newResourceFilterer(
|
||||
resourceKind,
|
||||
sess.apiResource.resourceKind,
|
||||
verb,
|
||||
sess.codecFactory,
|
||||
allowedResources,
|
||||
|
||||
@@ -100,6 +100,7 @@ func TestListPodRBAC(t *testing.T) {
|
||||
Name: types.Wildcard,
|
||||
Namespace: types.Wildcard,
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
})
|
||||
},
|
||||
@@ -123,6 +124,7 @@ func TestListPodRBAC(t *testing.T) {
|
||||
Name: types.Wildcard,
|
||||
Namespace: metav1.NamespaceDefault,
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
})
|
||||
},
|
||||
@@ -148,6 +150,7 @@ func TestListPodRBAC(t *testing.T) {
|
||||
Name: types.Wildcard,
|
||||
Namespace: "{{external.namespaces}}",
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
})
|
||||
},
|
||||
@@ -172,6 +175,7 @@ func TestListPodRBAC(t *testing.T) {
|
||||
Name: "nginx-*",
|
||||
Namespace: metav1.NamespaceDefault,
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
)
|
||||
@@ -196,6 +200,7 @@ func TestListPodRBAC(t *testing.T) {
|
||||
Name: "*",
|
||||
Namespace: metav1.NamespaceDefault,
|
||||
Verbs: []string{"get"},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
)
|
||||
@@ -221,6 +226,7 @@ func TestListPodRBAC(t *testing.T) {
|
||||
Name: types.Wildcard,
|
||||
Namespace: types.Wildcard,
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
)
|
||||
@@ -231,6 +237,7 @@ func TestListPodRBAC(t *testing.T) {
|
||||
Name: types.Wildcard,
|
||||
Namespace: metav1.NamespaceDefault,
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
)
|
||||
@@ -476,7 +483,6 @@ func TestListPodRBAC(t *testing.T) {
|
||||
return pods
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
// generate a kube client with user certs for auth
|
||||
@@ -562,6 +568,7 @@ func TestWatcherResponseWriter(t *testing.T) {
|
||||
Namespace: "*",
|
||||
Name: "*",
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: "core",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -576,6 +583,7 @@ func TestWatcherResponseWriter(t *testing.T) {
|
||||
Namespace: defaultNamespace,
|
||||
Name: "*",
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: "core",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -590,6 +598,7 @@ func TestWatcherResponseWriter(t *testing.T) {
|
||||
Namespace: defaultNamespace,
|
||||
Name: "*",
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: "core",
|
||||
},
|
||||
},
|
||||
denied: []types.KubernetesResource{
|
||||
@@ -598,6 +607,7 @@ func TestWatcherResponseWriter(t *testing.T) {
|
||||
Namespace: defaultNamespace,
|
||||
Name: "otherPod",
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: "core",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -612,6 +622,7 @@ func TestWatcherResponseWriter(t *testing.T) {
|
||||
Namespace: defaultNamespace,
|
||||
Name: "rand*",
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: "core",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -627,11 +638,10 @@ func TestWatcherResponseWriter(t *testing.T) {
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
userReader, userWriter := io.Pipe()
|
||||
negotiator := newClientNegotiator(&globalKubeCodecs)
|
||||
filterWrapper := newResourceFilterer(types.KindKubePod, types.KubeVerbWatch, &globalKubeCodecs, tt.args.allowed, tt.args.denied, utils.NewSlogLoggerForTests())
|
||||
filterWrapper := newResourceFilterer(types.KindKubePod, "core", types.KubeVerbWatch, &globalKubeCodecs, tt.args.allowed, tt.args.denied, utils.NewSlogLoggerForTests())
|
||||
// watcher parses the data written into itself and if the user is allowed to
|
||||
// receive the update, it writes the event into target.
|
||||
watcher, err := responsewriters.NewWatcherResponseWriter(newFakeResponseWriter(userWriter) /*target*/, negotiator, filterWrapper)
|
||||
@@ -867,6 +877,7 @@ func TestDeletePodCollectionRBAC(t *testing.T) {
|
||||
Name: types.Wildcard,
|
||||
Namespace: types.Wildcard,
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
})
|
||||
},
|
||||
@@ -890,6 +901,7 @@ func TestDeletePodCollectionRBAC(t *testing.T) {
|
||||
Name: types.Wildcard,
|
||||
Namespace: metav1.NamespaceDefault,
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
})
|
||||
},
|
||||
@@ -914,6 +926,7 @@ func TestDeletePodCollectionRBAC(t *testing.T) {
|
||||
Name: "nginx-*",
|
||||
Namespace: metav1.NamespaceDefault,
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
)
|
||||
@@ -1052,9 +1065,10 @@ func TestListClusterRoleRBAC(t *testing.T) {
|
||||
SetupRoleFunc: func(r types.Role) {
|
||||
r.SetKubeResources(types.Allow, []types.KubernetesResource{
|
||||
{
|
||||
Kind: types.KindKubeClusterRole,
|
||||
Name: types.Wildcard,
|
||||
Verbs: []string{types.Wildcard},
|
||||
Kind: types.KindKubeClusterRole,
|
||||
Name: types.Wildcard,
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
})
|
||||
},
|
||||
@@ -1075,9 +1089,10 @@ func TestListClusterRoleRBAC(t *testing.T) {
|
||||
r.SetKubeResources(types.Allow,
|
||||
[]types.KubernetesResource{
|
||||
{
|
||||
Kind: types.KindKubeClusterRole,
|
||||
Name: "nginx-*",
|
||||
Verbs: []string{types.Wildcard},
|
||||
Kind: types.KindKubeClusterRole,
|
||||
Name: "nginx-*",
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
)
|
||||
@@ -1276,9 +1291,10 @@ func TestCustomResourcesRBAC(t *testing.T) {
|
||||
SetupRoleFunc: func(r types.Role) {
|
||||
r.SetKubeResources(types.Allow, []types.KubernetesResource{
|
||||
{
|
||||
Kind: types.KindKubeNamespace,
|
||||
Name: types.Wildcard,
|
||||
Verbs: []string{types.Wildcard},
|
||||
Kind: types.KindKubeNamespace,
|
||||
Name: types.Wildcard,
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
})
|
||||
},
|
||||
@@ -1298,9 +1314,10 @@ func TestCustomResourcesRBAC(t *testing.T) {
|
||||
r.SetKubeResources(types.Allow,
|
||||
[]types.KubernetesResource{
|
||||
{
|
||||
Kind: types.KindKubeNamespace,
|
||||
Name: "dev",
|
||||
Verbs: []string{types.Wildcard},
|
||||
Kind: types.KindKubeNamespace,
|
||||
Name: "dev",
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
@@ -77,6 +77,7 @@ func TestSelfSubjectAccessReviewsRBAC(t *testing.T) {
|
||||
Namespace: types.Wildcard,
|
||||
Name: types.Wildcard,
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -94,6 +95,7 @@ func TestSelfSubjectAccessReviewsRBAC(t *testing.T) {
|
||||
Namespace: types.Wildcard,
|
||||
Name: types.Wildcard,
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -111,6 +113,7 @@ func TestSelfSubjectAccessReviewsRBAC(t *testing.T) {
|
||||
Namespace: types.Wildcard,
|
||||
Name: types.Wildcard,
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -128,6 +131,7 @@ func TestSelfSubjectAccessReviewsRBAC(t *testing.T) {
|
||||
Name: "pod-2",
|
||||
Namespace: "namespace-1",
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -145,12 +149,14 @@ func TestSelfSubjectAccessReviewsRBAC(t *testing.T) {
|
||||
Name: "pod-2",
|
||||
Namespace: "namespace-1",
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
{
|
||||
Kind: types.KindKubePod,
|
||||
Name: "pod-1",
|
||||
Namespace: "namespace-1",
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -168,6 +174,7 @@ func TestSelfSubjectAccessReviewsRBAC(t *testing.T) {
|
||||
Name: "pod-2",
|
||||
Namespace: "namespace-1",
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -185,6 +192,7 @@ func TestSelfSubjectAccessReviewsRBAC(t *testing.T) {
|
||||
Name: "pod-2",
|
||||
Namespace: "namespace-1",
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -197,9 +205,10 @@ func TestSelfSubjectAccessReviewsRBAC(t *testing.T) {
|
||||
kind: "namespaces",
|
||||
resources: []types.KubernetesResource{
|
||||
{
|
||||
Kind: types.KindKubeNamespace,
|
||||
Name: "namespace-2",
|
||||
Verbs: []string{types.Wildcard},
|
||||
Kind: types.KindKubeNamespace,
|
||||
Name: "namespace-2",
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -212,9 +221,10 @@ func TestSelfSubjectAccessReviewsRBAC(t *testing.T) {
|
||||
kind: "namespaces",
|
||||
resources: []types.KubernetesResource{
|
||||
{
|
||||
Kind: types.KindKubeNamespace,
|
||||
Name: "namespace",
|
||||
Verbs: []string{types.Wildcard},
|
||||
Kind: types.KindKubeNamespace,
|
||||
Name: "namespace",
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -227,9 +237,10 @@ func TestSelfSubjectAccessReviewsRBAC(t *testing.T) {
|
||||
kind: "pods",
|
||||
resources: []types.KubernetesResource{
|
||||
{
|
||||
Kind: types.KindKubeNamespace,
|
||||
Name: "namespace-2",
|
||||
Verbs: []string{types.Wildcard},
|
||||
Kind: types.KindKubeNamespace,
|
||||
Name: "namespace-2",
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -259,9 +270,10 @@ func TestSelfSubjectAccessReviewsRBAC(t *testing.T) {
|
||||
apiGroup: "resources.teleport.dev",
|
||||
resources: []types.KubernetesResource{
|
||||
{
|
||||
Kind: types.KindKubeNamespace,
|
||||
Name: "namespace-2",
|
||||
Verbs: []string{types.Wildcard},
|
||||
Kind: types.KindKubeNamespace,
|
||||
Name: "namespace-2",
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -275,9 +287,10 @@ func TestSelfSubjectAccessReviewsRBAC(t *testing.T) {
|
||||
apiGroup: "rbac.authorization.k8s.io",
|
||||
resources: []types.KubernetesResource{
|
||||
{
|
||||
Kind: types.KindKubeNamespace,
|
||||
Name: "namespace-2",
|
||||
Verbs: []string{types.Wildcard},
|
||||
Kind: types.KindKubeNamespace,
|
||||
Name: "namespace-2",
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -291,9 +304,10 @@ func TestSelfSubjectAccessReviewsRBAC(t *testing.T) {
|
||||
apiGroup: "rbac.authorization.k8s.io",
|
||||
resources: []types.KubernetesResource{
|
||||
{
|
||||
Kind: types.KindKubeClusterRole,
|
||||
Name: "role",
|
||||
Verbs: []string{types.Wildcard},
|
||||
Kind: types.KindKubeClusterRole,
|
||||
Name: "role",
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -307,9 +321,10 @@ func TestSelfSubjectAccessReviewsRBAC(t *testing.T) {
|
||||
apiGroup: "rbac.authorization.k8s.io",
|
||||
resources: []types.KubernetesResource{
|
||||
{
|
||||
Kind: types.KindKubeClusterRole,
|
||||
Name: "role",
|
||||
Verbs: []string{types.Wildcard},
|
||||
Kind: types.KindKubeClusterRole,
|
||||
Name: "role",
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -323,9 +338,10 @@ func TestSelfSubjectAccessReviewsRBAC(t *testing.T) {
|
||||
apiGroup: "rbac.authorization.k8s.io",
|
||||
resources: []types.KubernetesResource{
|
||||
{
|
||||
Kind: types.KindKubeClusterRole,
|
||||
Name: "role",
|
||||
Verbs: []string{types.Wildcard},
|
||||
Kind: types.KindKubeClusterRole,
|
||||
Name: "role",
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -339,9 +355,10 @@ func TestSelfSubjectAccessReviewsRBAC(t *testing.T) {
|
||||
apiGroup: "rbac.authorization.k8s.io",
|
||||
resources: []types.KubernetesResource{
|
||||
{
|
||||
Kind: types.KindKubeClusterRole,
|
||||
Name: "role",
|
||||
Verbs: []string{"get"},
|
||||
Kind: types.KindKubeClusterRole,
|
||||
Name: "role",
|
||||
Verbs: []string{"get"},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -355,9 +372,10 @@ func TestSelfSubjectAccessReviewsRBAC(t *testing.T) {
|
||||
namespace: "namespace-1",
|
||||
resources: []types.KubernetesResource{
|
||||
{
|
||||
Kind: types.KindKubeNamespace,
|
||||
Name: "namespace-1",
|
||||
Verbs: []string{types.Wildcard},
|
||||
Kind: types.KindKubeNamespace,
|
||||
Name: "namespace-1",
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -366,7 +384,6 @@ func TestSelfSubjectAccessReviewsRBAC(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
// create a user with full access to kubernetes Pods.
|
||||
|
||||
@@ -115,7 +115,7 @@ func TestSingleCertRouting(t *testing.T) {
|
||||
KubeUsers: roleKubeUsers,
|
||||
KubeGroups: roleKubeGroups,
|
||||
SetupRoleFunc: func(r types.Role) {
|
||||
r.SetKubeResources(types.Deny, []types.KubernetesResource{{Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard}}})
|
||||
r.SetKubeResources(types.Deny, []types.KubernetesResource{{Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard}, APIGroup: types.Wildcard}})
|
||||
},
|
||||
},
|
||||
assert: func(t *testing.T, restConfig *rest.Config) {
|
||||
@@ -143,7 +143,7 @@ func TestSingleCertRouting(t *testing.T) {
|
||||
KubeUsers: roleKubeUsers,
|
||||
KubeGroups: roleKubeGroups,
|
||||
SetupRoleFunc: func(r types.Role) {
|
||||
r.SetKubeResources(types.Allow, []types.KubernetesResource{{Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard}}})
|
||||
r.SetKubeResources(types.Allow, []types.KubernetesResource{{Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard}, APIGroup: types.Wildcard}})
|
||||
r.SetOptions(types.RoleOptions{
|
||||
RequireMFAType: types.RequireMFAType_SESSION,
|
||||
})
|
||||
@@ -165,7 +165,7 @@ func TestSingleCertRouting(t *testing.T) {
|
||||
KubeUsers: roleKubeUsers,
|
||||
KubeGroups: roleKubeGroups,
|
||||
SetupRoleFunc: func(r types.Role) {
|
||||
r.SetKubeResources(types.Allow, []types.KubernetesResource{{Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard}}})
|
||||
r.SetKubeResources(types.Allow, []types.KubernetesResource{{Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard}, APIGroup: types.Wildcard}})
|
||||
r.SetOptions(types.RoleOptions{
|
||||
RequireMFAType: types.RequireMFAType_SESSION,
|
||||
})
|
||||
|
||||
@@ -249,6 +249,7 @@ func getResourceFromRequest(req *http.Request, kubeDetails *kubeDetails) (*types
|
||||
Namespace: apiResource.namespace,
|
||||
Name: apiResource.resourceName,
|
||||
Verbs: []string{verb},
|
||||
APIGroup: apiResource.apiGroup,
|
||||
}, apiResource, nil
|
||||
}
|
||||
|
||||
|
||||
+50
-50
@@ -102,120 +102,120 @@ func Test_getResourceFromRequest(t *testing.T) {
|
||||
{path: "/apis/apps/v1/", want: nil},
|
||||
{path: "/api/v1/pods", want: nil},
|
||||
{path: "/api/v1/watch/pods", want: nil},
|
||||
{path: "/api/v1/namespaces/kube-system", want: &types.KubernetesResource{Kind: types.KindKubeNamespace, Name: "kube-system", Verbs: []string{"get"}}},
|
||||
{path: "/api/v1/watch/namespaces/kube-system", want: &types.KubernetesResource{Kind: types.KindKubeNamespace, Name: "kube-system", Verbs: []string{"watch"}}},
|
||||
{path: "/api/v1/namespaces/kube-system", want: &types.KubernetesResource{Kind: types.KindKubeNamespace, Name: "kube-system", Verbs: []string{"get"}, APIGroup: "core"}},
|
||||
{path: "/api/v1/watch/namespaces/kube-system", want: &types.KubernetesResource{Kind: types.KindKubeNamespace, Name: "kube-system", Verbs: []string{"watch"}, APIGroup: "core"}},
|
||||
{path: "/api/v1/namespaces/kube-system/pods", want: nil},
|
||||
{path: "/api/v1/watch/namespaces/kube-system/pods", want: nil},
|
||||
{path: "/api/v1/namespaces/kube-system/pods/foo", want: &types.KubernetesResource{Kind: types.KindKubePod, Namespace: "kube-system", Name: "foo", Verbs: []string{"get"}}},
|
||||
{path: "/api/v1/watch/namespaces/kube-system/pods/foo", want: &types.KubernetesResource{Kind: types.KindKubePod, Namespace: "kube-system", Name: "foo", Verbs: []string{"watch"}}},
|
||||
{path: "/api/v1/namespaces/kube-system/pods/foo", want: &types.KubernetesResource{Kind: types.KindKubePod, Namespace: "kube-system", Name: "foo", Verbs: []string{"get"}, APIGroup: "core"}},
|
||||
{path: "/api/v1/watch/namespaces/kube-system/pods/foo", want: &types.KubernetesResource{Kind: types.KindKubePod, Namespace: "kube-system", Name: "foo", Verbs: []string{"watch"}, APIGroup: "core"}},
|
||||
{path: "/apis/apiregistration.k8s.io/v1/apiservices/foo/status", want: nil},
|
||||
|
||||
// core
|
||||
// Pods
|
||||
{path: "/api/v1/pods", want: nil},
|
||||
{path: "/api/v1/namespaces/default/pods", want: nil},
|
||||
{path: "/api/v1/namespaces/default/pods/foo", want: &types.KubernetesResource{Kind: types.KindKubePod, Namespace: "default", Name: "foo", Verbs: []string{"get"}}},
|
||||
{path: "/api/v1/watch/namespaces/default/pods/foo", want: &types.KubernetesResource{Kind: types.KindKubePod, Namespace: "default", Name: "foo", Verbs: []string{"watch"}}},
|
||||
{path: "/api/v1/namespaces/kube-system/pods/foo/exec", want: &types.KubernetesResource{Kind: types.KindKubePod, Namespace: "kube-system", Name: "foo", Verbs: []string{"exec"}}},
|
||||
{path: "/api/v1/namespaces/kube-system/pods/foo/attach", want: &types.KubernetesResource{Kind: types.KindKubePod, Namespace: "kube-system", Name: "foo", Verbs: []string{"exec"}}},
|
||||
{path: "/api/v1/namespaces/kube-system/pods/foo/portforward", want: &types.KubernetesResource{Kind: types.KindKubePod, Namespace: "kube-system", Name: "foo", Verbs: []string{"portforward"}}},
|
||||
{path: "/api/v1/namespaces/default/pods", body: bodyFunc("Pod", "v1"), want: &types.KubernetesResource{Kind: types.KindKubePod, Namespace: "default", Name: "foo-create", Verbs: []string{"create"}}},
|
||||
{path: "/api/v1/namespaces/default/pods", body: bodyFuncWithoutGVK(), want: &types.KubernetesResource{Kind: types.KindKubePod, Namespace: "default", Name: "foo-create", Verbs: []string{"create"}}},
|
||||
{path: "/api/v1/namespaces/default/pods/foo", want: &types.KubernetesResource{Kind: types.KindKubePod, Namespace: "default", Name: "foo", Verbs: []string{"get"}, APIGroup: "core"}},
|
||||
{path: "/api/v1/watch/namespaces/default/pods/foo", want: &types.KubernetesResource{Kind: types.KindKubePod, Namespace: "default", Name: "foo", Verbs: []string{"watch"}, APIGroup: "core"}},
|
||||
{path: "/api/v1/namespaces/kube-system/pods/foo/exec", want: &types.KubernetesResource{Kind: types.KindKubePod, Namespace: "kube-system", Name: "foo", Verbs: []string{"exec"}, APIGroup: "core"}},
|
||||
{path: "/api/v1/namespaces/kube-system/pods/foo/attach", want: &types.KubernetesResource{Kind: types.KindKubePod, Namespace: "kube-system", Name: "foo", Verbs: []string{"exec"}, APIGroup: "core"}},
|
||||
{path: "/api/v1/namespaces/kube-system/pods/foo/portforward", want: &types.KubernetesResource{Kind: types.KindKubePod, Namespace: "kube-system", Name: "foo", Verbs: []string{"portforward"}, APIGroup: "core"}},
|
||||
{path: "/api/v1/namespaces/default/pods", body: bodyFunc("Pod", "v1"), want: &types.KubernetesResource{Kind: types.KindKubePod, Namespace: "default", Name: "foo-create", Verbs: []string{"create"}, APIGroup: "core"}},
|
||||
{path: "/api/v1/namespaces/default/pods", body: bodyFuncWithoutGVK(), want: &types.KubernetesResource{Kind: types.KindKubePod, Namespace: "default", Name: "foo-create", Verbs: []string{"create"}, APIGroup: "core"}},
|
||||
|
||||
// Secrets
|
||||
{path: "/api/v1/secrets", want: nil},
|
||||
{path: "/api/v1/namespaces/default/secrets", want: nil},
|
||||
{path: "/api/v1/namespaces/default/secrets/foo", want: &types.KubernetesResource{Kind: types.KindKubeSecret, Namespace: "default", Name: "foo", Verbs: []string{"get"}}},
|
||||
{path: "/api/v1/watch/namespaces/default/secrets/foo", want: &types.KubernetesResource{Kind: types.KindKubeSecret, Namespace: "default", Name: "foo", Verbs: []string{"watch"}}},
|
||||
{path: "/api/v1/namespaces/default/secrets", body: bodyFunc("Secret", "v1"), want: &types.KubernetesResource{Kind: types.KindKubeSecret, Namespace: "default", Name: "foo-create", Verbs: []string{"create"}}},
|
||||
{path: "/api/v1/namespaces/default/secrets", body: bodyFuncWithoutGVK(), want: &types.KubernetesResource{Kind: types.KindKubeSecret, Namespace: "default", Name: "foo-create", Verbs: []string{"create"}}},
|
||||
{path: "/api/v1/namespaces/default/secrets/foo", want: &types.KubernetesResource{Kind: types.KindKubeSecret, Namespace: "default", Name: "foo", Verbs: []string{"get"}, APIGroup: "core"}},
|
||||
{path: "/api/v1/watch/namespaces/default/secrets/foo", want: &types.KubernetesResource{Kind: types.KindKubeSecret, Namespace: "default", Name: "foo", Verbs: []string{"watch"}, APIGroup: "core"}},
|
||||
{path: "/api/v1/namespaces/default/secrets", body: bodyFunc("Secret", "v1"), want: &types.KubernetesResource{Kind: types.KindKubeSecret, Namespace: "default", Name: "foo-create", Verbs: []string{"create"}, APIGroup: "core"}},
|
||||
{path: "/api/v1/namespaces/default/secrets", body: bodyFuncWithoutGVK(), want: &types.KubernetesResource{Kind: types.KindKubeSecret, Namespace: "default", Name: "foo-create", Verbs: []string{"create"}, APIGroup: "core"}},
|
||||
|
||||
// Configmaps
|
||||
{path: "/api/v1/configmaps", want: nil},
|
||||
{path: "/api/v1/namespaces/default/configmaps", want: nil},
|
||||
{path: "/api/v1/namespaces/default/configmaps/foo", want: &types.KubernetesResource{Kind: types.KindKubeConfigmap, Namespace: "default", Name: "foo", Verbs: []string{"get"}}},
|
||||
{path: "/api/v1/watch/namespaces/default/configmaps/foo", want: &types.KubernetesResource{Kind: types.KindKubeConfigmap, Namespace: "default", Name: "foo", Verbs: []string{"watch"}}},
|
||||
{path: "/api/v1/namespaces/default/configmaps", body: bodyFunc("ConfigMap", "v1"), want: &types.KubernetesResource{Kind: types.KindKubeConfigmap, Namespace: "default", Name: "foo-create", Verbs: []string{"create"}}},
|
||||
{path: "/api/v1/namespaces/default/configmaps", body: bodyFuncWithoutGVK(), want: &types.KubernetesResource{Kind: types.KindKubeConfigmap, Namespace: "default", Name: "foo-create", Verbs: []string{"create"}}},
|
||||
{path: "/api/v1/namespaces/default/configmaps/foo", want: &types.KubernetesResource{Kind: types.KindKubeConfigmap, Namespace: "default", Name: "foo", Verbs: []string{"get"}, APIGroup: "core"}},
|
||||
{path: "/api/v1/watch/namespaces/default/configmaps/foo", want: &types.KubernetesResource{Kind: types.KindKubeConfigmap, Namespace: "default", Name: "foo", Verbs: []string{"watch"}, APIGroup: "core"}},
|
||||
{path: "/api/v1/namespaces/default/configmaps", body: bodyFunc("ConfigMap", "v1"), want: &types.KubernetesResource{Kind: types.KindKubeConfigmap, Namespace: "default", Name: "foo-create", Verbs: []string{"create"}, APIGroup: "core"}},
|
||||
{path: "/api/v1/namespaces/default/configmaps", body: bodyFuncWithoutGVK(), want: &types.KubernetesResource{Kind: types.KindKubeConfigmap, Namespace: "default", Name: "foo-create", Verbs: []string{"create"}, APIGroup: "core"}},
|
||||
|
||||
// Namespaces
|
||||
{path: "/api/v1/namespaces", want: nil},
|
||||
{path: "/api/v1/namespaces/default", want: &types.KubernetesResource{Kind: types.KindKubeNamespace, Name: "default", Verbs: []string{"get"}}},
|
||||
{path: "/api/v1/watch/namespaces/default", want: &types.KubernetesResource{Kind: types.KindKubeNamespace, Name: "default", Verbs: []string{"watch"}}},
|
||||
{path: "/api/v1/namespaces", body: bodyFunc("Namespace", "v1"), want: &types.KubernetesResource{Kind: types.KindKubeNamespace, Name: "foo-create", Verbs: []string{"create"}}},
|
||||
{path: "/api/v1/namespaces", body: bodyFuncWithoutGVK(), want: &types.KubernetesResource{Kind: types.KindKubeNamespace, Name: "foo-create", Verbs: []string{"create"}}},
|
||||
{path: "/api/v1/namespaces/default", want: &types.KubernetesResource{Kind: types.KindKubeNamespace, Name: "default", Verbs: []string{"get"}, APIGroup: "core"}},
|
||||
{path: "/api/v1/watch/namespaces/default", want: &types.KubernetesResource{Kind: types.KindKubeNamespace, Name: "default", Verbs: []string{"watch"}, APIGroup: "core"}},
|
||||
{path: "/api/v1/namespaces", body: bodyFunc("Namespace", "v1"), want: &types.KubernetesResource{Kind: types.KindKubeNamespace, Name: "foo-create", Verbs: []string{"create"}, APIGroup: "core"}},
|
||||
{path: "/api/v1/namespaces", body: bodyFuncWithoutGVK(), want: &types.KubernetesResource{Kind: types.KindKubeNamespace, Name: "foo-create", Verbs: []string{"create"}, APIGroup: "core"}},
|
||||
|
||||
// Nodes
|
||||
{path: "/api/v1/nodes", want: nil},
|
||||
{path: "/api/v1/nodes/foo/proxy/bar", want: &types.KubernetesResource{Kind: types.KindKubeNode, Name: "foo", Verbs: []string{"get"}}},
|
||||
{path: "/api/v1/nodes/foo/proxy/bar", want: &types.KubernetesResource{Kind: types.KindKubeNode, Name: "foo", Verbs: []string{"get"}, APIGroup: "core"}},
|
||||
// Services
|
||||
{path: "/api/v1/services", want: nil},
|
||||
{path: "/api/v1/namespaces/default/services", want: nil},
|
||||
{path: "/api/v1/namespaces/default/services/foo", want: &types.KubernetesResource{Kind: types.KindKubeService, Namespace: "default", Name: "foo", Verbs: []string{"get"}}},
|
||||
{path: "/api/v1/watch/namespaces/default/services/foo", want: &types.KubernetesResource{Kind: types.KindKubeService, Namespace: "default", Name: "foo", Verbs: []string{"watch"}}},
|
||||
{path: "/api/v1/namespaces/default/services", body: bodyFunc("Service", "v1"), want: &types.KubernetesResource{Kind: types.KindKubeService, Namespace: "default", Name: "foo-create", Verbs: []string{"create"}}},
|
||||
{path: "/api/v1/namespaces/default/services/foo", want: &types.KubernetesResource{Kind: types.KindKubeService, Namespace: "default", Name: "foo", Verbs: []string{"get"}, APIGroup: "core"}},
|
||||
{path: "/api/v1/watch/namespaces/default/services/foo", want: &types.KubernetesResource{Kind: types.KindKubeService, Namespace: "default", Name: "foo", Verbs: []string{"watch"}, APIGroup: "core"}},
|
||||
{path: "/api/v1/namespaces/default/services", body: bodyFunc("Service", "v1"), want: &types.KubernetesResource{Kind: types.KindKubeService, Namespace: "default", Name: "foo-create", Verbs: []string{"create"}, APIGroup: "core"}},
|
||||
|
||||
// ServiceAccounts
|
||||
{path: "/api/v1/serviceaccounts", want: nil},
|
||||
{path: "/api/v1/namespaces/default/serviceaccounts", want: nil},
|
||||
{path: "/api/v1/namespaces/default/serviceaccounts/foo", want: &types.KubernetesResource{Kind: types.KindKubeServiceAccount, Namespace: "default", Name: "foo", Verbs: []string{"get"}}},
|
||||
{path: "/api/v1/watch/namespaces/default/serviceaccounts/foo", want: &types.KubernetesResource{Kind: types.KindKubeServiceAccount, Namespace: "default", Name: "foo", Verbs: []string{"watch"}}},
|
||||
{path: "/api/v1/namespaces/default/serviceaccounts/foo", want: &types.KubernetesResource{Kind: types.KindKubeServiceAccount, Namespace: "default", Name: "foo", Verbs: []string{"get"}, APIGroup: "core"}},
|
||||
{path: "/api/v1/watch/namespaces/default/serviceaccounts/foo", want: &types.KubernetesResource{Kind: types.KindKubeServiceAccount, Namespace: "default", Name: "foo", Verbs: []string{"watch"}, APIGroup: "core"}},
|
||||
// PersistentVolumes
|
||||
{path: "/api/v1/persistentvolumes", want: nil},
|
||||
{path: "/api/v1/namespaces/default/persistentvolumes", want: nil},
|
||||
{path: "/api/v1/namespaces/default/persistentvolumes/foo", want: &types.KubernetesResource{Kind: types.KindKubePersistentVolume, Namespace: "default", Name: "foo", Verbs: []string{"get"}}},
|
||||
{path: "/api/v1/watch/namespaces/default/persistentvolumes/foo", want: &types.KubernetesResource{Kind: types.KindKubePersistentVolume, Namespace: "default", Name: "foo", Verbs: []string{"watch"}}},
|
||||
{path: "/api/v1/namespaces/default/persistentvolumes/foo", want: &types.KubernetesResource{Kind: types.KindKubePersistentVolume, Namespace: "default", Name: "foo", Verbs: []string{"get"}, APIGroup: "core"}},
|
||||
{path: "/api/v1/watch/namespaces/default/persistentvolumes/foo", want: &types.KubernetesResource{Kind: types.KindKubePersistentVolume, Namespace: "default", Name: "foo", Verbs: []string{"watch"}, APIGroup: "core"}},
|
||||
// PersistentVolumeClaims
|
||||
{path: "/api/v1/persistentvolumeclaims", want: nil},
|
||||
{path: "/api/v1/namespaces/default/persistentvolumeclaims", want: nil},
|
||||
{path: "/api/v1/namespaces/default/persistentvolumeclaims/foo", want: &types.KubernetesResource{Kind: types.KindKubePersistentVolumeClaim, Namespace: "default", Name: "foo", Verbs: []string{"get"}}},
|
||||
{path: "/api/v1/watch/namespaces/default/persistentvolumeclaims/foo", want: &types.KubernetesResource{Kind: types.KindKubePersistentVolumeClaim, Namespace: "default", Name: "foo", Verbs: []string{"watch"}}},
|
||||
{path: "/api/v1/namespaces/default/persistentvolumeclaims/foo", want: &types.KubernetesResource{Kind: types.KindKubePersistentVolumeClaim, Namespace: "default", Name: "foo", Verbs: []string{"get"}, APIGroup: "core"}},
|
||||
{path: "/api/v1/watch/namespaces/default/persistentvolumeclaims/foo", want: &types.KubernetesResource{Kind: types.KindKubePersistentVolumeClaim, Namespace: "default", Name: "foo", Verbs: []string{"watch"}, APIGroup: "core"}},
|
||||
|
||||
// apis/apps
|
||||
// Deployments
|
||||
{path: "/apis/apps/v1/deployments", want: nil},
|
||||
{path: "/apis/apps/v1/namespaces/default/deployments", want: nil},
|
||||
{path: "/apis/apps/v1/namespaces/default/deployments/foo", want: &types.KubernetesResource{Kind: types.KindKubeDeployment, Namespace: "default", Name: "foo", Verbs: []string{"get"}}},
|
||||
{path: "/apis/apps/v1/watch/namespaces/default/deployments/foo", want: &types.KubernetesResource{Kind: types.KindKubeDeployment, Namespace: "default", Name: "foo", Verbs: []string{"watch"}}},
|
||||
{path: "/apis/apps/v1/namespaces/default/deployments", body: bodyFunc("Deployment", "apps/v1"), want: &types.KubernetesResource{Kind: types.KindKubeDeployment, Namespace: "default", Name: "foo-create", Verbs: []string{"create"}}},
|
||||
{path: "/apis/apps/v1beta2/namespaces/default/deployments", body: bodyFunc("Deployment", "apps/v1beta2"), want: &types.KubernetesResource{Kind: types.KindKubeDeployment, Namespace: "default", Name: "foo-create", Verbs: []string{"create"}}},
|
||||
{path: "/apis/apps/v1/namespaces/default/deployments", body: bodyFuncWithoutGVK(), want: &types.KubernetesResource{Kind: types.KindKubeDeployment, Namespace: "default", Name: "foo-create", Verbs: []string{"create"}}},
|
||||
{path: "/apis/apps/v1/namespaces/default/deployments/foo", want: &types.KubernetesResource{Kind: types.KindKubeDeployment, Namespace: "default", Name: "foo", Verbs: []string{"get"}, APIGroup: "apps"}},
|
||||
{path: "/apis/apps/v1/watch/namespaces/default/deployments/foo", want: &types.KubernetesResource{Kind: types.KindKubeDeployment, Namespace: "default", Name: "foo", Verbs: []string{"watch"}, APIGroup: "apps"}},
|
||||
{path: "/apis/apps/v1/namespaces/default/deployments", body: bodyFunc("Deployment", "apps/v1"), want: &types.KubernetesResource{Kind: types.KindKubeDeployment, Namespace: "default", Name: "foo-create", Verbs: []string{"create"}, APIGroup: "apps"}},
|
||||
{path: "/apis/apps/v1beta2/namespaces/default/deployments", body: bodyFunc("Deployment", "apps/v1beta2"), want: &types.KubernetesResource{Kind: types.KindKubeDeployment, Namespace: "default", Name: "foo-create", Verbs: []string{"create"}, APIGroup: "apps"}},
|
||||
{path: "/apis/apps/v1/namespaces/default/deployments", body: bodyFuncWithoutGVK(), want: &types.KubernetesResource{Kind: types.KindKubeDeployment, Namespace: "default", Name: "foo-create", Verbs: []string{"create"}, APIGroup: "apps"}},
|
||||
|
||||
// Statefulsets
|
||||
{path: "/apis/apps/v1/statefulsets", want: nil},
|
||||
{path: "/apis/apps/v1/namespaces/default/statefulsets", want: nil},
|
||||
{path: "/apis/apps/v1/namespaces/default/statefulsets/foo", want: &types.KubernetesResource{Kind: types.KindKubeStatefulset, Namespace: "default", Name: "foo", Verbs: []string{"get"}}},
|
||||
{path: "/apis/apps/v1/watch/namespaces/default/statefulsets/foo", want: &types.KubernetesResource{Kind: types.KindKubeStatefulset, Namespace: "default", Name: "foo", Verbs: []string{"watch"}}},
|
||||
{path: "/apis/apps/v1/namespaces/default/statefulsets/foo", want: &types.KubernetesResource{Kind: types.KindKubeStatefulset, Namespace: "default", Name: "foo", Verbs: []string{"get"}, APIGroup: "apps"}},
|
||||
{path: "/apis/apps/v1/watch/namespaces/default/statefulsets/foo", want: &types.KubernetesResource{Kind: types.KindKubeStatefulset, Namespace: "default", Name: "foo", Verbs: []string{"watch"}, APIGroup: "apps"}},
|
||||
// Replicasets
|
||||
{path: "/apis/apps/v1/replicasets", want: nil},
|
||||
{path: "/apis/apps/v1/namespaces/default/replicasets", want: nil},
|
||||
{path: "/apis/apps/v1/namespaces/default/replicasets/foo", want: &types.KubernetesResource{Kind: types.KindKubeReplicaSet, Namespace: "default", Name: "foo", Verbs: []string{"get"}}},
|
||||
{path: "/apis/apps/v1/watch/namespaces/default/replicasets/foo", want: &types.KubernetesResource{Kind: types.KindKubeReplicaSet, Namespace: "default", Name: "foo", Verbs: []string{"watch"}}},
|
||||
{path: "/apis/apps/v1/namespaces/default/replicasets/foo", want: &types.KubernetesResource{Kind: types.KindKubeReplicaSet, Namespace: "default", Name: "foo", Verbs: []string{"get"}, APIGroup: "apps"}},
|
||||
{path: "/apis/apps/v1/watch/namespaces/default/replicasets/foo", want: &types.KubernetesResource{Kind: types.KindKubeReplicaSet, Namespace: "default", Name: "foo", Verbs: []string{"watch"}, APIGroup: "apps"}},
|
||||
// Daemonsets
|
||||
{path: "/apis/apps/v1/daemonsets", want: nil},
|
||||
{path: "/apis/apps/v1/namespaces/default/daemonsets", want: nil},
|
||||
{path: "/apis/apps/v1/namespaces/default/daemonsets/foo", want: &types.KubernetesResource{Kind: types.KindKubeDaemonSet, Namespace: "default", Name: "foo", Verbs: []string{"get"}}},
|
||||
{path: "/apis/apps/v1/watch/namespaces/default/daemonsets/foo", want: &types.KubernetesResource{Kind: types.KindKubeDaemonSet, Namespace: "default", Name: "foo", Verbs: []string{"watch"}}},
|
||||
{path: "/apis/apps/v1/namespaces/default/daemonsets/foo", want: &types.KubernetesResource{Kind: types.KindKubeDaemonSet, Namespace: "default", Name: "foo", Verbs: []string{"get"}, APIGroup: "apps"}},
|
||||
{path: "/apis/apps/v1/watch/namespaces/default/daemonsets/foo", want: &types.KubernetesResource{Kind: types.KindKubeDaemonSet, Namespace: "default", Name: "foo", Verbs: []string{"watch"}, APIGroup: "apps"}},
|
||||
|
||||
// apis/batch
|
||||
// Job
|
||||
{path: "/apis/batch/v1/jobs", want: nil},
|
||||
{path: "/apis/batch/v1/namespaces/default/jobs", want: nil},
|
||||
{path: "/apis/batch/v1/namespaces/default/jobs/foo", want: &types.KubernetesResource{Kind: types.KindKubeJob, Namespace: "default", Name: "foo", Verbs: []string{"get"}}},
|
||||
{path: "/apis/batch/v1/watch/namespaces/default/jobs/foo", want: &types.KubernetesResource{Kind: types.KindKubeJob, Namespace: "default", Name: "foo", Verbs: []string{"watch"}}},
|
||||
{path: "/apis/batch/v1/namespaces/default/jobs/foo", want: &types.KubernetesResource{Kind: types.KindKubeJob, Namespace: "default", Name: "foo", Verbs: []string{"get"}, APIGroup: "batch"}},
|
||||
{path: "/apis/batch/v1/watch/namespaces/default/jobs/foo", want: &types.KubernetesResource{Kind: types.KindKubeJob, Namespace: "default", Name: "foo", Verbs: []string{"watch"}, APIGroup: "batch"}},
|
||||
// CronJob
|
||||
{path: "/apis/batch/v1/cronjobs", want: nil},
|
||||
{path: "/apis/batch/v1/namespaces/default/cronjobs", want: nil},
|
||||
{path: "/apis/batch/v1/namespaces/default/cronjobs/foo", want: &types.KubernetesResource{Kind: types.KindKubeCronjob, Namespace: "default", Name: "foo", Verbs: []string{"get"}}},
|
||||
{path: "/apis/batch/v1/watch/namespaces/default/cronjobs/foo", want: &types.KubernetesResource{Kind: types.KindKubeCronjob, Namespace: "default", Name: "foo", Verbs: []string{"watch"}}},
|
||||
{path: "/apis/batch/v1/namespaces/default/cronjobs/foo", want: &types.KubernetesResource{Kind: types.KindKubeCronjob, Namespace: "default", Name: "foo", Verbs: []string{"get"}, APIGroup: "batch"}},
|
||||
{path: "/apis/batch/v1/watch/namespaces/default/cronjobs/foo", want: &types.KubernetesResource{Kind: types.KindKubeCronjob, Namespace: "default", Name: "foo", Verbs: []string{"watch"}, APIGroup: "batch"}},
|
||||
|
||||
// apis/certificates.k8s.io
|
||||
{path: "/apis/certificates.k8s.io/v1/certificatesigningrequests", want: nil},
|
||||
{path: "/apis/certificates.k8s.io/v1/certificatesigningrequests/foo", want: &types.KubernetesResource{Kind: types.KindKubeCertificateSigningRequest, Name: "foo", Verbs: []string{"get"}}},
|
||||
{path: "/apis/certificates.k8s.io/v1/certificatesigningrequests/foo", want: &types.KubernetesResource{Kind: types.KindKubeCertificateSigningRequest, Name: "foo", Verbs: []string{"get"}, APIGroup: "certificates.k8s.io"}},
|
||||
|
||||
// apis/networking.k8s.io
|
||||
{path: "/apis/networking.k8s.io/v1/ingresses", want: nil},
|
||||
{path: "/apis/networking.k8s.io/v1/ingresses/foo", want: &types.KubernetesResource{Kind: types.KindKubeIngress, Name: "foo", Verbs: []string{"get"}}},
|
||||
{path: "/apis/networking.k8s.io/v1/ingresses/foo", want: &types.KubernetesResource{Kind: types.KindKubeIngress, Name: "foo", Verbs: []string{"get"}, APIGroup: "networking.k8s.io"}},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
||||
@@ -465,7 +465,7 @@ func (c *TestContext) CreateUserWithTraitsAndRole(ctx context.Context, t *testin
|
||||
role.SetSessionRequirePolicies(roleSpec.SessionRequire)
|
||||
role.SetSessionJoinPolicies(roleSpec.SessionJoin)
|
||||
if roleSpec.SetupRoleFunc == nil {
|
||||
role.SetKubeResources(types.Allow, []types.KubernetesResource{{Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard}}})
|
||||
role.SetKubeResources(types.Allow, []types.KubernetesResource{{Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, Verbs: []string{types.Wildcard}, APIGroup: "core"}})
|
||||
} else {
|
||||
roleSpec.SetupRoleFunc(role)
|
||||
}
|
||||
|
||||
@@ -538,6 +538,8 @@ func (a *accessChecker) GetKubeResources(cluster types.KubeCluster) (allowed, de
|
||||
Kind: r.Kind,
|
||||
Namespace: namespace,
|
||||
Name: name,
|
||||
// TODO(@creack): Add support for Groups in AccessRequests.
|
||||
APIGroup: types.Wildcard,
|
||||
}
|
||||
// matchKubernetesResource checks if the Kubernetes Resource matches the tuple
|
||||
// (kind, namespace, kame) from the allowed/denied list and does not match the resource
|
||||
@@ -554,7 +556,7 @@ func (a *accessChecker) GetKubeResources(cluster types.KubeCluster) (allowed, de
|
||||
return rolesAllowed, rolesDenied
|
||||
}
|
||||
}
|
||||
return
|
||||
return allowed, denied
|
||||
}
|
||||
|
||||
// matchKubernetesResource checks if the Kubernetes Resource does not match any
|
||||
|
||||
@@ -45,6 +45,7 @@ func TestAccessCheckerKubeResources(t *testing.T) {
|
||||
Name: "dev",
|
||||
Namespace: "dev",
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
})
|
||||
rv.SetKubernetesLabels(types.Allow, kubeDevLabels)
|
||||
@@ -58,12 +59,14 @@ func TestAccessCheckerKubeResources(t *testing.T) {
|
||||
Name: "any1",
|
||||
Namespace: "any1",
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
{
|
||||
Kind: types.KindKubePod,
|
||||
Name: "any1",
|
||||
Namespace: "any2",
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
})
|
||||
rv.SetKubernetesLabels(types.Allow, kubeAnyLabels)
|
||||
@@ -79,12 +82,14 @@ func TestAccessCheckerKubeResources(t *testing.T) {
|
||||
Name: "any1",
|
||||
Namespace: "any1",
|
||||
Verbs: []string{types.KubeVerbList},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
{
|
||||
Kind: types.KindKubePod,
|
||||
Name: "any1",
|
||||
Namespace: "any2",
|
||||
Verbs: []string{types.KubeVerbList},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
})
|
||||
rv.SetKubernetesLabels(types.Allow, kubeAnyLabels)
|
||||
@@ -126,12 +131,14 @@ func TestAccessCheckerKubeResources(t *testing.T) {
|
||||
Name: "any1",
|
||||
Namespace: "any1",
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
{
|
||||
Kind: types.KindKubePod,
|
||||
Name: "any1",
|
||||
Namespace: "any2",
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
wantDenied: emptySet,
|
||||
@@ -158,18 +165,21 @@ func TestAccessCheckerKubeResources(t *testing.T) {
|
||||
Name: "any1",
|
||||
Namespace: "any1",
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
{
|
||||
Kind: types.KindKubePod,
|
||||
Name: "any1",
|
||||
Namespace: "any2",
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
{
|
||||
Kind: types.KindKubePod,
|
||||
Name: "dev",
|
||||
Namespace: "dev",
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
wantDenied: emptySet,
|
||||
@@ -221,6 +231,7 @@ func TestAccessCheckerKubeResources(t *testing.T) {
|
||||
Name: "dev",
|
||||
Namespace: "dev",
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
wantDenied: emptySet,
|
||||
@@ -302,18 +313,21 @@ func TestAccessCheckerKubeResources(t *testing.T) {
|
||||
Name: "any1",
|
||||
Namespace: "any1",
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
{
|
||||
Kind: types.KindKubePod,
|
||||
Name: "any1",
|
||||
Namespace: "any2",
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
{
|
||||
Kind: types.KindKubePod,
|
||||
Name: "dev",
|
||||
Namespace: "dev",
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
wantDenied: emptySet,
|
||||
@@ -353,6 +367,7 @@ func TestAccessCheckerKubeResources(t *testing.T) {
|
||||
Name: "dev",
|
||||
Namespace: "dev",
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
wantDenied: emptySet,
|
||||
@@ -392,12 +407,14 @@ func TestAccessCheckerKubeResources(t *testing.T) {
|
||||
Name: "any1",
|
||||
Namespace: "any1",
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
{
|
||||
Kind: types.KindKubePod,
|
||||
Name: "any1",
|
||||
Namespace: "any2",
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
wantDenied: emptySet,
|
||||
@@ -451,12 +468,14 @@ func TestAccessCheckerKubeResources(t *testing.T) {
|
||||
Name: "any1",
|
||||
Namespace: "any1",
|
||||
Verbs: []string{types.KubeVerbList},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
{
|
||||
Kind: types.KindKubePod,
|
||||
Name: "any1",
|
||||
Namespace: "any2",
|
||||
Verbs: []string{types.KubeVerbList},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
wantDenied: emptySet,
|
||||
@@ -483,12 +502,14 @@ func TestAccessCheckerKubeResources(t *testing.T) {
|
||||
Name: "any1",
|
||||
Namespace: "any1",
|
||||
Verbs: []string{types.KubeVerbList},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
{
|
||||
Kind: types.KindKubePod,
|
||||
Name: "any1",
|
||||
Namespace: "any2",
|
||||
Verbs: []string{types.KubeVerbList},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
wantDenied: emptySet,
|
||||
|
||||
@@ -2928,7 +2928,7 @@ func TestValidate_WithAllowRequestKubernetesResources(t *testing.T) {
|
||||
"*": {"*"},
|
||||
},
|
||||
KubernetesResources: []types.KubernetesResource{
|
||||
{Kind: "*", Namespace: "*", Name: "*", Verbs: []string{"*"}},
|
||||
{Kind: "*", Namespace: "*", Name: "*", Verbs: []string{"*"}, APIGroup: "*"},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -2941,7 +2941,7 @@ func TestValidate_WithAllowRequestKubernetesResources(t *testing.T) {
|
||||
"*": {"*"},
|
||||
},
|
||||
KubernetesResources: []types.KubernetesResource{
|
||||
{Kind: types.KindNamespace, Namespace: "*", Name: "*", Verbs: []string{"*"}},
|
||||
{Kind: types.KindNamespace, Namespace: "*", Name: "*", Verbs: []string{"*"}, APIGroup: "*"},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -2951,7 +2951,7 @@ func TestValidate_WithAllowRequestKubernetesResources(t *testing.T) {
|
||||
"*": {"*"},
|
||||
},
|
||||
KubernetesResources: []types.KubernetesResource{
|
||||
{Kind: types.KindKubePod, Namespace: "*", Name: "*", Verbs: []string{"*"}},
|
||||
{Kind: types.KindKubePod, Namespace: "*", Name: "*", Verbs: []string{"*"}, APIGroup: "*"},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -2961,7 +2961,7 @@ func TestValidate_WithAllowRequestKubernetesResources(t *testing.T) {
|
||||
"*": {"*"},
|
||||
},
|
||||
KubernetesResources: []types.KubernetesResource{
|
||||
{Kind: types.KindKubeDeployment, Namespace: "*", Name: "*", Verbs: []string{"*"}},
|
||||
{Kind: types.KindKubeDeployment, Namespace: "*", Name: "*", Verbs: []string{"*"}, APIGroup: "*"},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
+16
-15
@@ -47,7 +47,7 @@ func NewSystemAutomaticAccessApproverRole() types.Role {
|
||||
}
|
||||
role := &types.RoleV6{
|
||||
Kind: types.KindRole,
|
||||
Version: types.V8,
|
||||
Version: types.V7,
|
||||
Metadata: types.Metadata{
|
||||
Name: teleport.SystemAutomaticAccessApprovalRoleName,
|
||||
Namespace: apidefaults.Namespace,
|
||||
@@ -113,7 +113,7 @@ func NewPresetEditorRole() types.Role {
|
||||
// YAML.
|
||||
role := &types.RoleV6{
|
||||
Kind: types.KindRole,
|
||||
Version: types.V8,
|
||||
Version: types.V7,
|
||||
Metadata: types.Metadata{
|
||||
Name: teleport.PresetEditorRoleName,
|
||||
Namespace: apidefaults.Namespace,
|
||||
@@ -234,7 +234,7 @@ func NewPresetAccessRole() types.Role {
|
||||
// YAML.
|
||||
role := &types.RoleV6{
|
||||
Kind: types.KindRole,
|
||||
Version: types.V8,
|
||||
Version: types.V7,
|
||||
Metadata: types.Metadata{
|
||||
Name: teleport.PresetAccessRoleName,
|
||||
Namespace: apidefaults.Namespace,
|
||||
@@ -284,6 +284,7 @@ func NewPresetAccessRole() types.Role {
|
||||
Namespace: types.Wildcard,
|
||||
Name: types.Wildcard,
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: "",
|
||||
},
|
||||
},
|
||||
GitHubPermissions: []types.GitHubPermission{{
|
||||
@@ -326,7 +327,7 @@ func NewPresetAuditorRole() types.Role {
|
||||
// YAML.
|
||||
role := &types.RoleV6{
|
||||
Kind: types.KindRole,
|
||||
Version: types.V8,
|
||||
Version: types.V7,
|
||||
Metadata: types.Metadata{
|
||||
Name: teleport.PresetAuditorRoleName,
|
||||
Namespace: apidefaults.Namespace,
|
||||
@@ -371,7 +372,7 @@ func NewPresetReviewerRole() types.Role {
|
||||
|
||||
role := &types.RoleV6{
|
||||
Kind: types.KindRole,
|
||||
Version: types.V8,
|
||||
Version: types.V7,
|
||||
Metadata: types.Metadata{
|
||||
Name: teleport.PresetReviewerRoleName,
|
||||
Namespace: apidefaults.Namespace,
|
||||
@@ -398,7 +399,7 @@ func NewPresetRequesterRole() types.Role {
|
||||
|
||||
role := &types.RoleV6{
|
||||
Kind: types.KindRole,
|
||||
Version: types.V8,
|
||||
Version: types.V7,
|
||||
Metadata: types.Metadata{
|
||||
Name: teleport.PresetRequesterRoleName,
|
||||
Namespace: apidefaults.Namespace,
|
||||
@@ -425,7 +426,7 @@ func NewPresetGroupAccessRole() types.Role {
|
||||
|
||||
role := &types.RoleV6{
|
||||
Kind: types.KindRole,
|
||||
Version: types.V8,
|
||||
Version: types.V7,
|
||||
Metadata: types.Metadata{
|
||||
Name: teleport.PresetGroupAccessRoleName,
|
||||
Namespace: apidefaults.Namespace,
|
||||
@@ -459,7 +460,7 @@ func NewPresetDeviceAdminRole() types.Role {
|
||||
|
||||
return &types.RoleV6{
|
||||
Kind: types.KindRole,
|
||||
Version: types.V8,
|
||||
Version: types.V7,
|
||||
Metadata: types.Metadata{
|
||||
Name: teleport.PresetDeviceAdminRoleName,
|
||||
Namespace: apidefaults.Namespace,
|
||||
@@ -488,7 +489,7 @@ func NewPresetDeviceEnrollRole() types.Role {
|
||||
|
||||
return &types.RoleV6{
|
||||
Kind: types.KindRole,
|
||||
Version: types.V8,
|
||||
Version: types.V7,
|
||||
Metadata: types.Metadata{
|
||||
Name: teleport.PresetDeviceEnrollRoleName,
|
||||
Namespace: apidefaults.Namespace,
|
||||
@@ -518,7 +519,7 @@ func NewPresetRequireTrustedDeviceRole() types.Role {
|
||||
|
||||
return &types.RoleV6{
|
||||
Kind: types.KindRole,
|
||||
Version: types.V8,
|
||||
Version: types.V7,
|
||||
Metadata: types.Metadata{
|
||||
Name: teleport.PresetRequireTrustedDeviceRoleName,
|
||||
Namespace: apidefaults.Namespace,
|
||||
@@ -566,7 +567,7 @@ func NewPresetRequireTrustedDeviceRole() types.Role {
|
||||
func NewPresetWildcardWorkloadIdentityIssuerRole() types.Role {
|
||||
role := &types.RoleV6{
|
||||
Kind: types.KindRole,
|
||||
Version: types.V8,
|
||||
Version: types.V7,
|
||||
Metadata: types.Metadata{
|
||||
Name: teleport.PresetWildcardWorkloadIdentityIssuerRoleName,
|
||||
Namespace: apidefaults.Namespace,
|
||||
@@ -599,7 +600,7 @@ func NewSystemOktaAccessRole() types.Role {
|
||||
|
||||
role := &types.RoleV6{
|
||||
Kind: types.KindRole,
|
||||
Version: types.V8,
|
||||
Version: types.V7,
|
||||
Metadata: types.Metadata{
|
||||
Name: teleport.SystemOktaAccessRoleName,
|
||||
Namespace: apidefaults.Namespace,
|
||||
@@ -635,7 +636,7 @@ func NewSystemOktaRequesterRole() types.Role {
|
||||
|
||||
role := &types.RoleV6{
|
||||
Kind: types.KindRole,
|
||||
Version: types.V8,
|
||||
Version: types.V7,
|
||||
Metadata: types.Metadata{
|
||||
Name: teleport.SystemOktaRequesterRoleName,
|
||||
Namespace: apidefaults.Namespace,
|
||||
@@ -662,7 +663,7 @@ func NewSystemIdentityCenterAccessRole() types.Role {
|
||||
}
|
||||
return &types.RoleV6{
|
||||
Kind: types.KindRole,
|
||||
Version: types.V8,
|
||||
Version: types.V7,
|
||||
Metadata: types.Metadata{
|
||||
Name: teleport.SystemIdentityCenterAccessRoleName,
|
||||
Namespace: apidefaults.Namespace,
|
||||
@@ -689,7 +690,7 @@ func NewSystemIdentityCenterAccessRole() types.Role {
|
||||
func NewPresetTerraformProviderRole() types.Role {
|
||||
role := &types.RoleV6{
|
||||
Kind: types.KindRole,
|
||||
Version: types.V8,
|
||||
Version: types.V7,
|
||||
Metadata: types.Metadata{
|
||||
Name: teleport.PresetTerraformProviderRoleName,
|
||||
Namespace: apidefaults.Namespace,
|
||||
|
||||
@@ -540,6 +540,7 @@ func ApplyTraits(r types.Role, traits map[string][]string) (types.Role, error) {
|
||||
Namespace: namespace,
|
||||
Name: name,
|
||||
Verbs: verbs,
|
||||
APIGroup: rec.APIGroup,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1077,6 +1077,7 @@ func TestValidateRole(t *testing.T) {
|
||||
Namespace: "{{external.namespace",
|
||||
Name: "{{email.localz(external.email)}}",
|
||||
Verbs: []string{"{{external.verbs"},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1087,6 +1088,7 @@ func TestValidateRole(t *testing.T) {
|
||||
Namespace: "{{external.namespace",
|
||||
Name: "{{email.localz(external.email)}}",
|
||||
Verbs: []string{"{{external.verbs"},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -9289,11 +9291,13 @@ func TestKubeResourcesMatcher(t *testing.T) {
|
||||
Kind: types.KindKubePod,
|
||||
Namespace: "dev",
|
||||
Name: types.Wildcard,
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
{
|
||||
Kind: types.KindKubePod,
|
||||
Namespace: "default",
|
||||
Name: "nginx-*",
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -9303,6 +9307,7 @@ func TestKubeResourcesMatcher(t *testing.T) {
|
||||
Kind: types.KindKubePod,
|
||||
Namespace: "default",
|
||||
Name: "restricted",
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -9318,6 +9323,7 @@ func TestKubeResourcesMatcher(t *testing.T) {
|
||||
Kind: types.KindKubePod,
|
||||
Namespace: "prod",
|
||||
Name: "pod",
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -9333,6 +9339,7 @@ func TestKubeResourcesMatcher(t *testing.T) {
|
||||
Kind: types.KindKubePod,
|
||||
Namespace: `^[($`,
|
||||
Name: `^[($`,
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -608,12 +608,14 @@ func TestKubeResourceMatchesRegex(t *testing.T) {
|
||||
Namespace: "default",
|
||||
Name: "name",
|
||||
Verbs: []string{types.KubeVerbGet},
|
||||
APIGroup: "stable.example.com",
|
||||
},
|
||||
resources: []types.KubernetesResource{
|
||||
{
|
||||
Kind: types.KindKubeNamespace,
|
||||
Name: "default",
|
||||
Verbs: []string{types.KubeVerbGet},
|
||||
Kind: types.KindKubeNamespace,
|
||||
Name: "default",
|
||||
Verbs: []string{types.KubeVerbGet},
|
||||
APIGroup: "*",
|
||||
},
|
||||
},
|
||||
assert: require.NoError,
|
||||
@@ -627,12 +629,14 @@ func TestKubeResourceMatchesRegex(t *testing.T) {
|
||||
Namespace: "default",
|
||||
Name: "name",
|
||||
Verbs: []string{types.KubeVerbUpdate},
|
||||
APIGroup: "stable.example.com",
|
||||
},
|
||||
resources: []types.KubernetesResource{
|
||||
{
|
||||
Kind: types.KindKubeNamespace,
|
||||
Name: "default",
|
||||
Verbs: []string{types.KubeVerbGet},
|
||||
Kind: types.KindKubeNamespace,
|
||||
Name: "default",
|
||||
Verbs: []string{types.KubeVerbGet},
|
||||
APIGroup: "*",
|
||||
},
|
||||
},
|
||||
assert: require.NoError,
|
||||
|
||||
@@ -4361,10 +4361,12 @@ func TestClusterKubeResourcesGet(t *testing.T) {
|
||||
Kind: types.KindKubePod,
|
||||
Namespace: types.Wildcard,
|
||||
Name: types.Wildcard,
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
{
|
||||
Kind: types.KindKubeNamespace,
|
||||
Name: types.Wildcard,
|
||||
Kind: types.KindKubeNamespace,
|
||||
Name: types.Wildcard,
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -4455,7 +4457,6 @@ func TestClusterKubeResourcesGet(t *testing.T) {
|
||||
pack := proxy.authPack(t, user, roleWithFullAccess(user))
|
||||
|
||||
for _, tc := range tt {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
endpoint := pack.clt.Endpoint("webapi", "sites", env.server.ClusterName(), "kubernetes", "resources")
|
||||
params := url.Values{}
|
||||
@@ -6886,6 +6887,7 @@ func TestDiagnoseKubeConnection(t *testing.T) {
|
||||
Namespace: types.Wildcard,
|
||||
Name: types.Wildcard,
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -6911,6 +6913,7 @@ func TestDiagnoseKubeConnection(t *testing.T) {
|
||||
Namespace: types.Wildcard,
|
||||
Name: types.Wildcard,
|
||||
Verbs: []string{types.Wildcard},
|
||||
APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -218,7 +218,8 @@ spec:
|
||||
kubernetes_labels:
|
||||
'*': '*'
|
||||
kubernetes_resources:
|
||||
- kind: pod
|
||||
- api_group: '*'
|
||||
kind: pod
|
||||
name: '*'
|
||||
namespace: '*'
|
||||
logins:
|
||||
@@ -253,7 +254,7 @@ version: v8
|
||||
KubernetesLabels: types.Labels{types.Wildcard: []string{types.Wildcard}},
|
||||
KubernetesResources: []types.KubernetesResource{
|
||||
{
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard,
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -2612,7 +2612,7 @@ func TestKubeCredentialsLock(t *testing.T) {
|
||||
KubeUsers: []string{alice.GetName()},
|
||||
KubernetesResources: []types.KubernetesResource{
|
||||
{
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard,
|
||||
Kind: types.KindKubePod, Name: types.Wildcard, Namespace: types.Wildcard, APIGroup: types.Wildcard,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user