Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #2265: Refactor SubjectAccessReview API #2400

Merged
merged 2 commits into from Aug 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Expand Up @@ -9,6 +9,7 @@
* Fix #2389: KubernetesServer does not use value from https in crud mode
* Fix #2306: Make KubernetesServer CRUD mode work with informers
* Fix #2418: CertificateSigningRequest doesn't implement Namespaced
* Fix #2265: InAnyNamespace uses invalid api endpoint for SelfSubjectAccessReviews

#### Improvements
* Fix #2331: Fixed documentation for namespaced informer for all custom types implementing `Namespaced` interface
Expand All @@ -27,6 +28,10 @@
* Fix #2287: Add support for V1 and V1Beta1 CustomResourceDefinition
* Fix #2319: Create Config without using auto-configure functionality or setting env variables

_**Note**_: Some classes have been moved to other packages:
- CustomResourceDefinition has been moved to `io.fabric8.kubernetes.api.model.apiextensions.v1` and `io.fabric8.kubernetes.api.model.apiextensions.v1beta1`
- SubjectAccessReview, SelfSubjectAccessReview, LocalSubjectAccessReview and SelfSubjectRulesReview have been moved to `io.fabric8.kubernetes.api.model.authorization.v1` and `io.fabric8.kubernetes.api.model.authorization.v1beta1`

### 4.10.3 (2020-07-14)
#### Bugs
* Fix #2285: Raw CustomResource API createOrReplace does not propagate exceptions from create
Expand Down
85 changes: 85 additions & 0 deletions doc/CHEATSHEET.md
Expand Up @@ -24,6 +24,10 @@ This document contains common usages of different resources using Fabric8 Kubern
* [PersistentVolume](#persistentvolume)
* [NetworkPolicy](#networkpolicy)
* [PodDisruptionBudget](#poddisruptionbudget)
* [SelfSubjectAccessReview](#selfsubjectaccessreview)
* [SubjectAccessReview](#subjectaccessreview)
* [LocalSubjectAccessReview](#localsubjectaccessreview)
* [SelfSubjectRulesReview](#selfsubjectrulesreview)
* [Top/Metrics](#fetching-metrics)
* [Generic Resource API](#resource-api)
* [Generic ResourceList API](#resourcelist-api)
Expand Down Expand Up @@ -1566,6 +1570,87 @@ PodDisruptionBudgetList pdbList = client.policy().podDisruptionBudget().inNamesp
Boolean deleted = client.policy().podDisruptionBudget().inNamespace("default").withName("poddisruptionbudget1").delete();
```

### SelfSubjectAccessReview
- Create `SelfSubjectAccessReview`(equivalent of `kubectl auth can-i create deployments --namespace dev`):
```
try (KubernetesClient client = new DefaultKubernetesClient()) {
SelfSubjectAccessReview ssar = new SelfSubjectAccessReviewBuilder()
.withNewSpec()
.withNewResourceAttributes()
.withGroup("apps")
.withResource("deployments")
.withVerb("create")
.withNamespace("dev")
.endResourceAttributes()
.endSpec()
.build();
ssar = client.authorization().v1().selfSubjectAccessReview().create(ssar);
System.out.println("Allowed: "+ ssar.getStatus().getAllowed());
}
```

### SubjectAccessReview
- Create `SubjectAccessReview`:
```
try (KubernetesClient client = new DefaultKubernetesClient()) {
SubjectAccessReview sar = new SubjectAccessReviewBuilder()
.withNewSpec()
.withNewResourceAttributes()
.withGroup("apps")
.withResource("deployments")
.withVerb("create")
.withNamespace("default")
.endResourceAttributes()
.withUser("kubeadmin")
.endSpec()
.build();
sar = client.authorization().v1().subjectAccessReview().create(sar);
System.out.println("Allowed: "+ sar.getStatus().getAllowed());
}
```
### LocalSubjectAccessReview
- Create `LocalSubjectAccessReview`:
```
try (KubernetesClient client = new DefaultKubernetesClient()) {
LocalSubjectAccessReview lsar = new LocalSubjectAccessReviewBuilder()
.withNewMetadata().withNamespace("default").endMetadata()
.withNewSpec()
.withUser("foo")
.withNewResourceAttributes()
.withNamespace("default")
.withVerb("get")
.withGroup("apps")
.withResource("pods")
.endResourceAttributes()
.endSpec()
.build();
lsar = client.authorization().v1().localSubjectAccessReview().inNamespace("default").create(lsar);
System.out.println(lsar.getStatus().getAllowed());
}
```

### SelfSubjectRulesReview
- Create `SelfSubjectRulesReview`:
```
try (KubernetesClient client = new DefaultKubernetesClient()) {
SelfSubjectRulesReview selfSubjectRulesReview = new SelfSubjectRulesReviewBuilder()
.withNewMetadata().withName("foo").endMetadata()
.withNewSpec()
.withNamespace("default")
.endSpec()
.build();
selfSubjectRulesReview = client.authorization().v1().selfSubjectRulesReview().create(selfSubjectRulesReview);
System.out.println(selfSubjectRulesReview.getStatus().getIncomplete());
System.out.println("non resource rules: " + selfSubjectRulesReview.getStatus().getNonResourceRules().size());
System.out.println("resource rules: " + selfSubjectRulesReview.getStatus().getResourceRules().size());
}
```

### Fetching Metrics
Kubernetes Client also supports fetching metrics from API server if metrics are enabled on it. You can access metrics via `client.top()`. Here are some examples of its usage:
- Get `NodeMetrics` for all nodes:
Expand Down
@@ -0,0 +1,39 @@
/**
* Copyright (C) 2015 Red Hat, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.fabric8.kubernetes.client;

import io.fabric8.kubernetes.client.dsl.AuthorizationAPIGroupDSL;
import okhttp3.OkHttpClient;

public class AuthorizationAPIGroupClient extends BaseClient implements AuthorizationAPIGroupDSL {
public AuthorizationAPIGroupClient() {
super();
}

public AuthorizationAPIGroupClient(OkHttpClient httpClient, final Config config) {
super(httpClient, config);
}

@Override
public V1AuthorizationAPIGroupDSL v1() {
return adapt(V1AuthorizationAPIGroupClient.class);
}

@Override
public V1beta1AuthorizationAPIGroupDSL v1beta1() {
return adapt(V1beta1AuthorizationAPIGroupClient.class);
}
}
Expand Up @@ -13,18 +13,25 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.fabric8.kubernetes.client;

package io.fabric8.openshift.client.dsl;
import okhttp3.OkHttpClient;

import io.fabric8.kubernetes.api.model.Doneable;
import io.fabric8.kubernetes.client.dsl.Createable;
import io.fabric8.openshift.api.model.SubjectAccessReview;
import io.fabric8.openshift.api.model.SubjectAccessReviewFluentImpl;
import io.fabric8.openshift.api.model.SubjectAccessReviewResponse;
public class AuthorizationAPIGroupExtensionAdapter extends APIGroupExtensionAdapter<AuthorizationAPIGroupClient> {

@Override
protected String getAPIGroupName() {
return "authorization";
}

@Override
public Class<AuthorizationAPIGroupClient> getExtensionType() {
return AuthorizationAPIGroupClient.class;
}

@Override
protected AuthorizationAPIGroupClient newInstance(Client client) {
return new AuthorizationAPIGroupClient(client.adapt(OkHttpClient.class), client.getConfiguration());
}

public abstract class CreateableSubjectAccessReview extends
SubjectAccessReviewFluentImpl<CreateableSubjectAccessReview>
implements
Doneable<SubjectAccessReviewResponse>,
Createable<SubjectAccessReview, SubjectAccessReviewResponse, CreateableSubjectAccessReview> {
}
Expand Up @@ -136,6 +136,11 @@ public AutoscalingAPIGroupDSL autoscaling() {
return delegate.autoscaling();
}

@Override
public AuthorizationAPIGroupDSL authorization() {
return delegate.authorization();
}

@Override
public NetworkAPIGroupDSL network() { return delegate.network(); }

Expand Down Expand Up @@ -251,11 +256,6 @@ public MixedOperation<ConfigMap, ConfigMapList, DoneableConfigMap, Resource<Conf
return delegate.configMaps();
}

@Override
public SubjectAccessReviewDSL subjectAccessReviewAuth() {
return delegate.subjectAccessReviewAuth();
}

@Override
public MixedOperation<LimitRange, LimitRangeList, DoneableLimitRange, Resource<LimitRange, DoneableLimitRange>> limitRanges() {
return delegate.limitRanges();
Expand Down
Expand Up @@ -76,12 +76,15 @@
import io.fabric8.kubernetes.api.model.certificates.CertificateSigningRequest;
import io.fabric8.kubernetes.api.model.certificates.CertificateSigningRequestList;
import io.fabric8.kubernetes.api.model.certificates.DoneableCertificateSigningRequest;
import io.fabric8.kubernetes.api.model.authentication.DoneableTokenReview;
import io.fabric8.kubernetes.api.model.authentication.TokenReview;
import io.fabric8.kubernetes.api.model.coordination.v1.DoneableLease;
import io.fabric8.kubernetes.api.model.coordination.v1.Lease;
import io.fabric8.kubernetes.api.model.coordination.v1.LeaseList;
import io.fabric8.kubernetes.client.dsl.*;
import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext;
import io.fabric8.kubernetes.client.dsl.internal.ClusterOperationsImpl;
import io.fabric8.kubernetes.client.dsl.internal.CreateOnlyResourceOperationsImpl;
import io.fabric8.kubernetes.client.dsl.internal.apiextensions.v1beta1.CustomResourceDefinitionOperationsImpl;
import io.fabric8.kubernetes.client.dsl.internal.CustomResourceOperationContext;
import io.fabric8.kubernetes.client.dsl.internal.CustomResourceOperationsImpl;
Expand All @@ -98,7 +101,6 @@
import io.fabric8.kubernetes.client.dsl.internal.RawCustomResourceOperationsImpl;
import io.fabric8.kubernetes.client.dsl.internal.core.v1.ReplicationControllerOperationsImpl;
import io.fabric8.kubernetes.client.dsl.internal.core.v1.ServiceOperationsImpl;
import io.fabric8.kubernetes.client.dsl.internal.SubjectAccessReviewDSLImpl;
import io.fabric8.kubernetes.client.dsl.internal.coordination.v1.LeaseOperationsImpl;
import io.fabric8.kubernetes.client.dsl.internal.core.v1.BindingOperationsImpl;
import io.fabric8.kubernetes.client.dsl.internal.core.v1.ConfigMapOperationsImpl;
Expand All @@ -112,6 +114,7 @@
import io.fabric8.kubernetes.client.extended.leaderelection.LeaderElectorBuilder;
import io.fabric8.kubernetes.client.utils.Serialization;
import io.fabric8.kubernetes.client.informers.SharedInformerFactory;
import io.fabric8.kubernetes.client.utils.Utils;
import okhttp3.OkHttpClient;

import java.io.InputStream;
Expand Down Expand Up @@ -302,6 +305,16 @@ public NonNamespaceOperation<CertificateSigningRequest, CertificateSigningReques
return new CertificateSigningRequestOperationsImpl(httpClient, getConfiguration());
}

@Override
public AuthorizationAPIGroupDSL authorization() {
return adapt(AuthorizationAPIGroupClient.class);
}

@Override
public Createable<TokenReview, TokenReview, DoneableTokenReview> tokenReviews() {
return new CreateOnlyResourceOperationsImpl<>(httpClient, getConfiguration(), "authentication.k8s.io", "v1", Utils.getPluralFromKind(TokenReview.class.getSimpleName()), TokenReview.class);
}

@Override
public <T extends HasMetadata, L extends KubernetesResourceList<T>, D extends Doneable<T>> MixedOperation<T, L, D, Resource<T, D>> customResources(CustomResourceDefinitionContext crdContext, Class<T> resourceType, Class<L> listClass, Class<D> doneClass) {
return new CustomResourceOperationsImpl<>(new CustomResourceOperationContext().withOkhttpClient(httpClient).withConfig(getConfiguration())
Expand Down Expand Up @@ -401,11 +414,6 @@ public AutoscalingAPIGroupDSL autoscaling() {
@Override
public SettingsAPIGroupDSL settings() { return adapt(SettingsAPIGroupClient.class); }

@Override
public SubjectAccessReviewDSL subjectAccessReviewAuth() {
return new SubjectAccessReviewDSLImpl(httpClient, getConfiguration());
}

@Override
public SharedInformerFactory informers() {
return new SharedInformerFactory(ForkJoinPool.commonPool(), httpClient, getConfiguration());
Expand Down
Expand Up @@ -72,6 +72,8 @@
import io.fabric8.kubernetes.api.model.certificates.CertificateSigningRequest;
import io.fabric8.kubernetes.api.model.certificates.CertificateSigningRequestList;
import io.fabric8.kubernetes.api.model.certificates.DoneableCertificateSigningRequest;
import io.fabric8.kubernetes.api.model.authentication.DoneableTokenReview;
import io.fabric8.kubernetes.api.model.authentication.TokenReview;
import io.fabric8.kubernetes.api.model.coordination.v1.DoneableLease;
import io.fabric8.kubernetes.api.model.coordination.v1.Lease;
import io.fabric8.kubernetes.api.model.coordination.v1.LeaseList;
Expand Down Expand Up @@ -457,11 +459,18 @@ public interface KubernetesClient extends Client {
MixedOperation<LimitRange, LimitRangeList, DoneableLimitRange, Resource<LimitRange, DoneableLimitRange>> limitRanges();

/**
* SubjectAccessReview operations. (authorization/v1)
* Authorization operations. (authorization.k8s.io/v1 and authorization.k8s.io/v1beta1)
*
* @return SubjectAccessReviewDSL object for dealing with SubjectAccessReviewOperations
* @return AuthorizationAPIGroupDSL object for dealing with Authorization objects
*/
SubjectAccessReviewDSL subjectAccessReviewAuth();
AuthorizationAPIGroupDSL authorization();

/**
* API for creating authentication.k8s.io/v1 TokenReviews
*
* @return CreateOnlyResourceOperations instance for creating TokenReview object
*/
Createable<TokenReview, TokenReview, DoneableTokenReview> tokenReviews();

/**
* Get an instance of Kubernetes Client informer factory. It allows you to construct and
Expand Down
@@ -0,0 +1,63 @@
/**
* Copyright (C) 2015 Red Hat, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.fabric8.kubernetes.client;

import io.fabric8.kubernetes.api.model.authorization.v1.DoneableLocalSubjectAccessReview;
import io.fabric8.kubernetes.api.model.authorization.v1.DoneableSelfSubjectAccessReview;
import io.fabric8.kubernetes.api.model.authorization.v1.DoneableSelfSubjectRulesReview;
import io.fabric8.kubernetes.api.model.authorization.v1.DoneableSubjectAccessReview;
import io.fabric8.kubernetes.api.model.authorization.v1.LocalSubjectAccessReview;
import io.fabric8.kubernetes.api.model.authorization.v1.SelfSubjectAccessReview;
import io.fabric8.kubernetes.api.model.authorization.v1.SelfSubjectRulesReview;
import io.fabric8.kubernetes.api.model.authorization.v1.SubjectAccessReview;
import io.fabric8.kubernetes.client.dsl.Createable;
import io.fabric8.kubernetes.client.dsl.internal.LocalCreateOnlyResourceReviewOperationsImpl;
import io.fabric8.kubernetes.client.dsl.internal.CreateOnlyResourceOperationsImpl;
import io.fabric8.kubernetes.client.utils.Utils;
import okhttp3.OkHttpClient;

public class V1AuthorizationAPIGroupClient extends BaseClient implements V1AuthorizationAPIGroupDSL {
public static final String AUTHORIZATION_APIGROUP = "authorization.k8s.io";
public static final String AUTHORIZATION_APIVERSION = "v1";

public V1AuthorizationAPIGroupClient() {
super();
}

public V1AuthorizationAPIGroupClient(OkHttpClient httpClient, final Config config) {
super(httpClient, config);
}

@Override
public Createable<SelfSubjectAccessReview, SelfSubjectAccessReview, DoneableSelfSubjectAccessReview> selfSubjectAccessReview() {
return new CreateOnlyResourceOperationsImpl<>(getHttpClient(), getConfiguration(), AUTHORIZATION_APIGROUP, AUTHORIZATION_APIVERSION, Utils.getPluralFromKind(io.fabric8.kubernetes.api.model.authorization.v1beta1.SelfSubjectAccessReview.class.getSimpleName()), SelfSubjectAccessReview.class);
}

@Override
public Createable<SubjectAccessReview, SubjectAccessReview, DoneableSubjectAccessReview> subjectAccessReview() {
return new CreateOnlyResourceOperationsImpl<>(getHttpClient(), getConfiguration(), AUTHORIZATION_APIGROUP, AUTHORIZATION_APIVERSION, Utils.getPluralFromKind(io.fabric8.kubernetes.api.model.authorization.v1beta1.SubjectAccessReview.class.getSimpleName()), SubjectAccessReview.class);
}

@Override
public LocalCreateOnlyResourceReviewOperationsImpl<LocalSubjectAccessReview, DoneableLocalSubjectAccessReview> localSubjectAccessReview() {
return new LocalCreateOnlyResourceReviewOperationsImpl<>(getHttpClient(), getConfiguration(), AUTHORIZATION_APIGROUP, AUTHORIZATION_APIVERSION, Utils.getPluralFromKind(io.fabric8.kubernetes.api.model.authorization.v1beta1.LocalSubjectAccessReview.class.getSimpleName()), LocalSubjectAccessReview.class);
}

@Override
public Createable<SelfSubjectRulesReview, SelfSubjectRulesReview, DoneableSelfSubjectRulesReview> selfSubjectRulesReview() {
return new CreateOnlyResourceOperationsImpl<>(getHttpClient(), getConfiguration(), AUTHORIZATION_APIGROUP, AUTHORIZATION_APIVERSION, Utils.getPluralFromKind(io.fabric8.kubernetes.api.model.authorization.v1beta1.SelfSubjectRulesReview.class.getSimpleName()), SelfSubjectRulesReview.class);
}
}