Skip to content

Commit 161cfd6

Browse files
committed
Merge branch 'develop' into feature/wdt
2 parents 8995675 + 2a6694c commit 161cfd6

File tree

13 files changed

+622
-196
lines changed

13 files changed

+622
-196
lines changed

kubernetes/internal/generate-security-policy.sh

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,12 @@ rules:
111111
- apiGroups: ["extensions"]
112112
resources: ["ingresses"]
113113
verbs: ["get", "list", "watch", "create", "update", "patch", "delete", "deletecollection"]
114+
- apiGroups: ["authentication.k8s.io"]
115+
resources: ["tokenreviews"]
116+
verbs: ["create"]
117+
- apiGroups: ["authorization.k8s.io"]
118+
resources: ["selfsubjectaccessreviews", "localsubjectaccessreviews", "subjectaccessreviews", "selfsubjectrulesreviews"]
119+
verbs: ["create"]
114120
---
115121
kind: ClusterRole
116122
apiVersion: rbac.authorization.k8s.io/v1beta1
@@ -259,4 +265,4 @@ EOF
259265
#
260266
echo "Create the WebLogic Operator Security configuration using kubectl as follows: kubectl create -f ${SCRIPT}"
261267
#
262-
echo "Ensure you start the API server with the --authorization-mode=RBAC option."
268+
echo "Ensure you start the API server with the --authorization-mode=RBAC option."

operator/src/main/java/oracle/kubernetes/operator/Main.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ private static void begin() {
220220
HealthCheckHelper healthCheck = new HealthCheckHelper(namespace, targetNamespaces);
221221
version = healthCheck.performK8sVersionCheck();
222222
healthCheck.performNonSecurityChecks();
223-
healthCheck.performSecurityChecks(serviceAccountName);
223+
healthCheck.performSecurityChecks(version);
224224
} catch (ApiException e) {
225225
LOGGER.warning(MessageKeys.EXCEPTION, e);
226226
}

operator/src/main/java/oracle/kubernetes/operator/helpers/AuthenticationProxy.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public V1TokenReviewStatus check(String principal, String token) {
3636
try {
3737
boolean allowed = authorizationProxy.check(principal,
3838
AuthorizationProxy.Operation.create,
39-
AuthorizationProxy.Resource.tokenreviews,
39+
AuthorizationProxy.Resource.TOKENREVIEWS,
4040
null,
4141
AuthorizationProxy.Scope.cluster,
4242
null);

operator/src/main/java/oracle/kubernetes/operator/helpers/AuthorizationProxy.java

Lines changed: 96 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
import io.kubernetes.client.ApiException;
99
import io.kubernetes.client.models.V1ObjectMeta;
1010
import io.kubernetes.client.models.V1ResourceAttributes;
11+
import io.kubernetes.client.models.V1SelfSubjectAccessReview;
12+
import io.kubernetes.client.models.V1SelfSubjectAccessReviewSpec;
13+
import io.kubernetes.client.models.V1SelfSubjectRulesReview;
14+
import io.kubernetes.client.models.V1SelfSubjectRulesReviewSpec;
1115
import io.kubernetes.client.models.V1SubjectAccessReview;
1216
import io.kubernetes.client.models.V1SubjectAccessReviewSpec;
1317
import io.kubernetes.client.models.V1SubjectAccessReviewStatus;
@@ -37,18 +41,50 @@ public enum Operation {
3741
}
3842

3943
public enum Resource {
40-
pods,
41-
services,
42-
namespaces,
43-
customresources,
44-
customresourcedefinitions,
45-
domains,
46-
tokenreviews,
47-
networkpolicies,
48-
secrets,
49-
persistentvolumes,
50-
persistentvolumeclaims,
51-
ingresses
44+
CONFIGMAPS ("configmaps", ""),
45+
PODS ("pods", ""),
46+
LOGS ("pods", "logs", ""),
47+
EXEC ("pods", "exec", ""),
48+
PODTEMPLATES ("podtemplates", ""),
49+
EVENTS ("events", ""),
50+
SERVICES ("services", ""),
51+
NAMESPACES ("namespaces", ""),
52+
JOBS ("jobs", "batch"),
53+
CRONJOBS ("cronjobs", "batch"),
54+
CRDS ("customresourcedefinitions", "apiextensions.k8s.io"),
55+
DOMAINS ("domains", "weblogic.oracle"),
56+
DOMAINSTATUSS ("domains", "status", "weblogic.oracle"),
57+
SUBJECTACCESSREVIEWS ("subjectaccessreviews", "authorization.k8s.io"),
58+
SELFSUBJECTACCESSREVIEWS ("selfsubjectaccessreviews", "authorization.k8s.io"),
59+
LOCALSUBJECTACCESSREVIEWS ("localsubjectaccessreviews", "authorization.k8s.io"),
60+
SELFSUBJECTRULESREVIEWS ("selfsubjectrulesreviews", "authorization.k8s.io"),
61+
TOKENREVIEWS ("tokenreviews", "authentication.k8s.io"),
62+
SECRETS ("secrets", ""),
63+
PERSISTENTVOLUMES ("persistentvolumes", ""),
64+
PERSISTENTVOLUMECLAIMS ("persistentvolumeclaims", ""),
65+
STORAGECLASSES ("storageclasses", "storage.k8s.io"),
66+
PODPRESETS ("podpresets" , "settings.k8s.io"),
67+
INGRESSES ("ingresses", "extensions"),
68+
NETWORKPOLICIES ("networkpolicies", "extensions"),
69+
PODSECURITYPOLICIES ("podsecuritypolicies", "extensions");
70+
71+
private final String resource;
72+
private final String subResource;
73+
private final String apiGroup;
74+
75+
Resource(String resource, String apiGroup) {
76+
this(resource, "", apiGroup);
77+
}
78+
79+
Resource(String resource, String subResource, String apiGroup) {
80+
this.resource = resource;
81+
this.subResource = subResource;
82+
this.apiGroup = apiGroup;
83+
}
84+
85+
public String getResource() { return resource; }
86+
public String getSubResource() { return subResource; }
87+
public String getAPIGroup() { return apiGroup; }
5288
}
5389

5490
public enum Scope {
@@ -104,6 +140,24 @@ public boolean check(String principal, final List<String> groups, Operation oper
104140
return result;
105141
}
106142

143+
public boolean check(Operation operation, Resource resource, String resourceName, Scope scope, String namespaceName) {
144+
LOGGER.entering();
145+
V1SelfSubjectAccessReview subjectAccessReview = prepareSelfSubjectAccessReview(operation, resource, resourceName, scope, namespaceName);
146+
try {
147+
CallBuilderFactory factory = ContainerResolver.getInstance().getContainer().getSPI(CallBuilderFactory.class);
148+
subjectAccessReview = factory.create().createSelfSubjectAccessReview(subjectAccessReview);
149+
} catch (ApiException e) {
150+
LOGGER.severe(MessageKeys.APIEXCEPTION_FROM_SUBJECT_ACCESS_REVIEW, e);
151+
LOGGER.exiting(Boolean.FALSE);
152+
return Boolean.FALSE;
153+
154+
}
155+
V1SubjectAccessReviewStatus subjectAccessReviewStatus = subjectAccessReview.getStatus();
156+
Boolean result = subjectAccessReviewStatus.isAllowed();
157+
LOGGER.exiting(result);
158+
return result;
159+
}
160+
107161
/**
108162
* Prepares an instance of SubjectAccessReview and returns same.
109163
*
@@ -133,6 +187,21 @@ private V1SubjectAccessReview prepareSubjectAccessReview(String principal, final
133187
return subjectAccessReview;
134188
}
135189

190+
private V1SelfSubjectAccessReview prepareSelfSubjectAccessReview(Operation operation, Resource resource, String resourceName, Scope scope, String namespaceName) {
191+
LOGGER.entering();
192+
V1SelfSubjectAccessReviewSpec subjectAccessReviewSpec = new V1SelfSubjectAccessReviewSpec();
193+
194+
subjectAccessReviewSpec.setResourceAttributes(prepareResourceAttributes(operation, resource, resourceName, scope, namespaceName));
195+
196+
V1SelfSubjectAccessReview subjectAccessReview = new V1SelfSubjectAccessReview();
197+
subjectAccessReview.setApiVersion("authorization.k8s.io/v1");
198+
subjectAccessReview.setKind("SelfSubjectAccessReview");
199+
subjectAccessReview.setMetadata(new V1ObjectMeta());
200+
subjectAccessReview.setSpec(subjectAccessReviewSpec);
201+
LOGGER.exiting(subjectAccessReview);
202+
return subjectAccessReview;
203+
}
204+
136205
/**
137206
* Prepares an instance of ResourceAttributes and returns same.
138207
*
@@ -150,12 +219,9 @@ private V1ResourceAttributes prepareResourceAttributes(Operation operation, Reso
150219
resourceAttributes.setVerb(operation.toString());
151220
}
152221
if (null != resource) {
153-
resourceAttributes.setResource(resource.toString());
154-
}
155-
156-
String apiGroup = getApiGroup(resource);
157-
if (apiGroup != null) {
158-
resourceAttributes.setGroup(apiGroup);
222+
resourceAttributes.setResource(resource.resource);
223+
resourceAttributes.setSubresource(resource.subResource);
224+
resourceAttributes.setGroup(resource.apiGroup);
159225
}
160226

161227
if (null != resourceName) {
@@ -168,25 +234,18 @@ private V1ResourceAttributes prepareResourceAttributes(Operation operation, Reso
168234
LOGGER.exiting(resourceAttributes);
169235
return resourceAttributes;
170236
}
171-
172-
private String getApiGroup(Resource resource) {
173-
if (resource == Resource.domains) {
174-
return "weblogic.oracle";
175-
}
176-
177-
if (resource == Resource.customresourcedefinitions) {
178-
return "apiextensions.k8s.io";
179-
}
180-
181-
if (resource == Resource.tokenreviews) {
182-
return "authentication.k8s.io";
183-
}
184-
185-
if (resource == Resource.ingresses) {
186-
return "extensions";
237+
238+
public V1SelfSubjectRulesReview review(String namespace) {
239+
V1SelfSubjectRulesReview subjectRulesReview = new V1SelfSubjectRulesReview();
240+
V1SelfSubjectRulesReviewSpec spec = new V1SelfSubjectRulesReviewSpec();
241+
spec.setNamespace(namespace);
242+
subjectRulesReview.setSpec(spec);
243+
CallBuilderFactory factory = ContainerResolver.getInstance().getContainer().getSPI(CallBuilderFactory.class);
244+
try {
245+
return factory.create().createSelfSubjectRulesReview(subjectRulesReview);
246+
} catch (ApiException e) {
247+
LOGGER.warning(MessageKeys.EXCEPTION, e);
248+
return null;
187249
}
188-
189-
// TODO - do we need to specify the api group for any of the other Resource values?
190-
return null;
191250
}
192251
}

operator/src/main/java/oracle/kubernetes/operator/helpers/CallBuilder.java

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
import io.kubernetes.client.models.V1Pod;
4141
import io.kubernetes.client.models.V1PodList;
4242
import io.kubernetes.client.models.V1Secret;
43+
import io.kubernetes.client.models.V1SelfSubjectAccessReview;
44+
import io.kubernetes.client.models.V1SelfSubjectRulesReview;
4345
import io.kubernetes.client.models.V1Service;
4446
import io.kubernetes.client.models.V1ServiceList;
4547
import io.kubernetes.client.models.V1Status;
@@ -1670,6 +1672,76 @@ public Step createSubjectAccessReviewAsync(V1SubjectAccessReview body, ResponseS
16701672
return createRequestAsync(responseStep, new RequestParams("createSubjectAccessReview", null, null, body), CREATE_SUBJECTACCESSREVIEW);
16711673
}
16721674

1675+
/* Self Subject Access Review */
1676+
1677+
/**
1678+
* Create self subject access review
1679+
* @param body Body
1680+
* @return Created self subject access review
1681+
* @throws ApiException API Exception
1682+
*/
1683+
public V1SelfSubjectAccessReview createSelfSubjectAccessReview(V1SelfSubjectAccessReview body) throws ApiException {
1684+
ApiClient client = helper.take();
1685+
try {
1686+
return new AuthorizationV1Api(client).createSelfSubjectAccessReview(body, pretty);
1687+
} finally {
1688+
helper.recycle(client);
1689+
}
1690+
}
1691+
1692+
private com.squareup.okhttp.Call createSelfSubjectAccessReviewAsync(ApiClient client, V1SelfSubjectAccessReview body, ApiCallback<V1SelfSubjectAccessReview> callback) throws ApiException {
1693+
return new AuthorizationV1Api(client).createSelfSubjectAccessReviewAsync(body, pretty, callback);
1694+
}
1695+
1696+
private final CallFactory<V1SelfSubjectAccessReview> CREATE_SELFSUBJECTACCESSREVIEW = (requestParams, usage, cont, callback) -> {
1697+
return createSelfSubjectAccessReviewAsync(usage, (V1SelfSubjectAccessReview) requestParams.body, callback);
1698+
};
1699+
1700+
/**
1701+
* Asynchronous step for creating self subject access review
1702+
* @param body Body
1703+
* @param responseStep Response step for when call completes
1704+
* @return Asynchronous step
1705+
*/
1706+
public Step createSelfSubjectAccessReviewAsync(V1SelfSubjectAccessReview body, ResponseStep<V1SelfSubjectAccessReview> responseStep) {
1707+
return createRequestAsync(responseStep, new RequestParams("createSelfSubjectAccessReview", null, null, body), CREATE_SELFSUBJECTACCESSREVIEW);
1708+
}
1709+
1710+
/* Self Subject Rules Review */
1711+
1712+
/**
1713+
* Create self subject rules review
1714+
* @param body Body
1715+
* @return Created self subject rules review
1716+
* @throws ApiException API Exception
1717+
*/
1718+
public V1SelfSubjectRulesReview createSelfSubjectRulesReview(V1SelfSubjectRulesReview body) throws ApiException {
1719+
ApiClient client = helper.take();
1720+
try {
1721+
return new AuthorizationV1Api(client).createSelfSubjectRulesReview(body, pretty);
1722+
} finally {
1723+
helper.recycle(client);
1724+
}
1725+
}
1726+
1727+
private com.squareup.okhttp.Call createSelfSubjectRulesReviewAsync(ApiClient client, V1SelfSubjectRulesReview body, ApiCallback<V1SelfSubjectRulesReview> callback) throws ApiException {
1728+
return new AuthorizationV1Api(client).createSelfSubjectRulesReviewAsync(body, pretty, callback);
1729+
}
1730+
1731+
private final CallFactory<V1SelfSubjectRulesReview> CREATE_SELFSUBJECTRULESREVIEW = (requestParams, usage, cont, callback) -> {
1732+
return createSelfSubjectRulesReviewAsync(usage, (V1SelfSubjectRulesReview) requestParams.body, callback);
1733+
};
1734+
1735+
/**
1736+
* Asynchronous step for creating self subject rules review
1737+
* @param body Body
1738+
* @param responseStep Response step for when call completes
1739+
* @return Asynchronous step
1740+
*/
1741+
public Step createSelfSubjectRulesReviewAsync(V1SelfSubjectRulesReview body, ResponseStep<V1SelfSubjectRulesReview> responseStep) {
1742+
return createRequestAsync(responseStep, new RequestParams("createSelfSubjectRulesReview", null, null, body), CREATE_SELFSUBJECTRULESREVIEW);
1743+
}
1744+
16731745
/* Token Review */
16741746

16751747
/**
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Copyright 2018, Oracle Corporation and/or its affiliates. All rights reserved.
2+
// Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl.
3+
4+
package oracle.kubernetes.operator.helpers;
5+
6+
import java.util.function.Supplier;
7+
8+
import io.kubernetes.client.ApiClient;
9+
10+
public interface ClientFactory extends Supplier<ApiClient> {
11+
12+
}

operator/src/main/java/oracle/kubernetes/operator/helpers/ClientPool.java

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,18 @@
99
import oracle.kubernetes.operator.logging.LoggingFacade;
1010
import oracle.kubernetes.operator.logging.LoggingFactory;
1111
import oracle.kubernetes.operator.logging.MessageKeys;
12+
import oracle.kubernetes.operator.work.Container;
13+
import oracle.kubernetes.operator.work.ContainerResolver;
1214

15+
import java.io.IOException;
1316
import java.util.concurrent.TimeUnit;
1417
import java.util.concurrent.atomic.AtomicBoolean;
1518

1619
public class ClientPool extends Pool<ApiClient> {
1720
private static final LoggingFacade LOGGER = LoggingFactory.getLogger("Operator", "Operator");
1821
private static final ClientPool SINGLETON = new ClientPool();
19-
20-
private final AtomicBoolean first = new AtomicBoolean(true);
22+
23+
private static final DefaultClientFactory FACTORY = new DefaultClientFactory();
2124

2225
public static ClientPool getInstance() {
2326
return SINGLETON;
@@ -37,10 +40,16 @@ private ApiClient getApiClient() {
3740
ApiClient client = null;
3841
LOGGER.fine(MessageKeys.CREATING_API_CLIENT);
3942
try {
40-
client = Config.defaultClient();
41-
if (first.getAndSet(false)) {
42-
Configuration.setDefaultApiClient(client);
43+
ClientFactory factory = null;
44+
Container c = ContainerResolver.getInstance().getContainer();
45+
if (c != null) {
46+
factory = c.getSPI(ClientFactory.class);
47+
}
48+
if (factory == null) {
49+
factory = FACTORY;
4350
}
51+
52+
client = factory.get();
4453
} catch (Throwable e) {
4554
LOGGER.warning(MessageKeys.EXCEPTION, e);
4655
}
@@ -53,4 +62,22 @@ private ApiClient getApiClient() {
5362
return client;
5463
}
5564

65+
private static class DefaultClientFactory implements ClientFactory {
66+
private final AtomicBoolean first = new AtomicBoolean(true);
67+
68+
@Override
69+
public ApiClient get() {
70+
ApiClient client;
71+
try {
72+
client = Config.defaultClient();
73+
if (first.getAndSet(false)) {
74+
Configuration.setDefaultApiClient(client);
75+
}
76+
return client;
77+
} catch (IOException e) {
78+
throw new RuntimeException(e);
79+
}
80+
}
81+
82+
}
5683
}

0 commit comments

Comments
 (0)