Skip to content

Commit e29173a

Browse files
authored
Merge branch 'develop' into issue_241
2 parents 4809b7a + 7691f5f commit e29173a

File tree

79 files changed

+61751
-97
lines changed

Some content is hidden

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

79 files changed

+61751
-97
lines changed

docs/SUMMARY.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
- [The `chime-live` Cluster](./operations/chime-live-cluster.md)
1414
- [Deploy to Heroku](./operations/heroku.md)
1515
- [Deploy to Your Own Cluster](./operations/byok8s.md)
16+
- [Limited Cluster Access for Deployment][1]
1617
- [Code of Conduct](CODE_OF_CONDUCT.md)
1718
- [Maintainers](MAINTAINERS.md)
1819
- [Glossary](GLOSSARY.md)
20+
21+
[1]: ./operations/limited-kubeconfigs/limited-kubeconfigs.md
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
# Creating Kubeconfigs with Limited Permissions
2+
3+
## Create a Role
4+
5+
Kubernetes has two primary resources which represent a set of permissions,
6+
Roles and ClusterRoles. ClusterRoles apply to resources in all namespaces,
7+
whereas Roles are limited to a specific namespace. Let's create a Role in the
8+
chime namespace which will allow read/write access to Deployments and
9+
read-only access to Pods.
10+
11+
deployer.yaml:
12+
13+
```
14+
apiVersion: rbac.authorization.k8s.io/v1
15+
kind: Role
16+
metadata:
17+
name: deployer
18+
namespace: chime
19+
rules:
20+
- apiGroups:
21+
- apps
22+
resources:
23+
- deployments
24+
verbs:
25+
# we are _not_ including 'create' and 'delete'
26+
- get
27+
- list
28+
- watch
29+
- update
30+
- patch
31+
- apiGroups:
32+
- ""
33+
resources:
34+
- pods
35+
verbs:
36+
# so that we can observe our pods getting created
37+
- get
38+
- list
39+
- watch
40+
```
41+
42+
## Create a ServiceAccount
43+
44+
One of the subjects which can take on a Role is a ServiceAccount. Let's
45+
create a ServiceAccount called penn-deployer in the chime namespace:
46+
47+
```
48+
apiVersion: v1
49+
kind: ServiceAccount
50+
metadata:
51+
name: penn-deployer
52+
namespace: chime
53+
```
54+
55+
## Create a RoleBinding
56+
57+
We can now give the ServiceAccount the Role that we created earlier using a
58+
RoleBinding in the chime namespace.
59+
60+
```
61+
apiVersion: rbac.authorization.k8s.io/v1
62+
kind: RoleBinding
63+
metadata:
64+
name: penn-deployer:deployer
65+
namespace: chime
66+
roleRef:
67+
apiGroup: rbac.authorization.k8s.io
68+
kind: Role
69+
name: deployer
70+
subjects:
71+
- kind: ServiceAccount
72+
name: penn-deployer
73+
namespace: chime
74+
```
75+
76+
## Grabbing the token for the ServiceAccount
77+
78+
Every ServiceAccount gets a token, lets grab it.
79+
80+
```
81+
k get secrets -n chime
82+
```
83+
84+
Look for `penn-deployer-token-<hash>`
85+
86+
```
87+
k get secrets -n chime penn-deployer-token-<hash>
88+
```
89+
90+
Grab the "token:" base64 encoded token.
91+
92+
*base64 decode this token, which will produce base64*
93+
94+
## Creating a token-based kubeconfig
95+
96+
Now take a look at the Kubeconfig that you are currently using. Does it use a
97+
token? If so, you can construct a Kubeconfig for this ServiceAccount by copying
98+
your kubeconfig and replacing the token and user name with this decoded token
99+
and the user name "penn-deployer".
100+
101+
It will look something like this:
102+
103+
```
104+
apiVersion: v1
105+
kind: Config
106+
preferences: {}
107+
108+
clusters:
109+
- name: chime-cluster
110+
cluster:
111+
certificate-authority-data: <ca-cert-base64, same as existing>
112+
server: https://<server-hostname>:<server-port>
113+
114+
users:
115+
- name: penn-deployer
116+
user:
117+
as-user-extra: {}
118+
token: <ServiceAccount token! Be very sure that this is the ServiceAccount token!>
119+
120+
contexts:
121+
- name: penn-deployer-chime
122+
context:
123+
cluster: chime-cluster
124+
user: penn-deployer
125+
namespace: chime
126+
127+
current-context: penn-deployer-chime
128+
```
129+
130+
## Test out your token-based Kubeconfig
131+
132+
You can now use this ServiceAccount to modify Deployments, and view Pods, but do nothing else.
133+
134+
```
135+
$ k get pods -A
136+
Error from server (Forbidden): pods is forbidden: User "system:serviceaccount:chime:penn-deployer" cannot list resource "pods" in API group "" at the cluster scope
137+
```
138+
139+
```
140+
$ export KUBECONFIG=new-kubeconfig.yaml
141+
$ k get pods -n chime
142+
$ k get deployments -n chime
143+
# deploy version 0.5.0
144+
$ k set image deployment/chime -n chime chime=docker.pkg.github.com/codeforphilly/chime/penn-chime:0.5.0 --record
145+
# observe status of deployment
146+
$ k get pods -n chime
147+
```
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
apiVersion: rbac.authorization.k8s.io/v1
2+
kind: Role
3+
metadata:
4+
name: deployer
5+
namespace: chime
6+
rules:
7+
- apiGroups:
8+
- apps/v1
9+
resources:
10+
- deployments
11+
verbs:
12+
# we are _not_ including 'create' and 'delete'
13+
- get
14+
- list
15+
- watch
16+
- update
17+
- patch
18+
- apiGroups:
19+
- ""
20+
resources:
21+
- pods
22+
verbs:
23+
# so that we can observe our pods getting created
24+
- get
25+
- list
26+
- watch
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
apiVersion: rbac.authorization.k8s.io/v1
2+
kind: RoleBinding
3+
metadata:
4+
name: penn-deployer:deployer
5+
namespace: chime
6+
roleRef:
7+
apiGroup: rbac.authorization.k8s.io
8+
kind: Role
9+
name: deployer
10+
subjects:
11+
- kind: ServiceAccount
12+
name: penn-deployer
13+
namespace: chime
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
apiVersion: v1
2+
kind: ServiceAccount
3+
metadata:
4+
name: penn-deployer
5+
namespace: chime

k8s-preprod/app.yaml

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
apiVersion: v1
2+
kind: Namespace
3+
metadata:
4+
name: chime
5+
6+
---
7+
8+
apiVersion: apps/v1
9+
kind: Deployment
10+
metadata:
11+
name: chime
12+
namespace: chime
13+
labels:
14+
app: chime
15+
spec:
16+
replicas: 15
17+
strategy:
18+
type: Recreate
19+
selector:
20+
matchLabels:
21+
app: chime
22+
template:
23+
metadata:
24+
labels:
25+
app: chime
26+
spec:
27+
containers:
28+
- image: docker.pkg.github.com/codeforphilly/chime/penn-chime:0.4.1
29+
name: chime
30+
ports:
31+
- containerPort: 8000
32+
name: http
33+
protocol: TCP
34+
imagePullSecrets:
35+
- name: regcred
36+
---
37+
38+
apiVersion: v1
39+
kind: Service
40+
metadata:
41+
name: chime
42+
namespace: chime
43+
labels:
44+
app: chime
45+
spec:
46+
selector:
47+
app: chime
48+
ports:
49+
- name: http
50+
port: 80
51+
protocol: TCP
52+
targetPort: 8000
53+
54+
---
55+
56+
apiVersion: extensions/v1beta1
57+
kind: Ingress
58+
metadata:
59+
name: chime
60+
namespace: chime
61+
labels:
62+
app: chime
63+
annotations:
64+
kubernetes.io/ingress.class: nginx
65+
certmanager.k8s.io/cluster-issuer: letsencrypt-prod
66+
nginx.ingress.kubernetes.io/proxy-body-size: "0"
67+
spec:
68+
tls:
69+
- hosts:
70+
- penn-chime.bus.phl.io
71+
- penn-chime-alt.bus.phl.io
72+
secretName: tls-secret
73+
rules:
74+
- host: penn-chime.bus.phl.io
75+
http:
76+
paths:
77+
- path: /
78+
backend:
79+
serviceName: chime
80+
servicePort: 80
81+
- host: penn-chime-alt.bus.phl.io
82+
http:
83+
paths:
84+
- path: /
85+
backend:
86+
serviceName: chime
87+
servicePort: 80
88+
89+
---
90+
91+
apiVersion: extensions/v1beta1
92+
kind: Ingress
93+
metadata:
94+
name: chime-static
95+
namespace: chime
96+
labels:
97+
app: chime
98+
annotations:
99+
nginx.ingress.kubernetes.io/proxy-buffering: "on" # Important!
100+
nginx.ingress.kubernetes.io/configuration-snippet: |
101+
location / {
102+
sub_filter </head>
103+
'<!-- Google Tag Manager -->
104+
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
105+
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
106+
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
107+
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
108+
})(window,document,'script','dataLayer','GTM-KBZ6ZKX');</script>
109+
<!-- End Google Tag Manager -->';
110+
sub_filter </body>
111+
'<!-- Google Tag Manager (noscript) -->
112+
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-KBZ6ZKX"
113+
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
114+
<!-- End Google Tag Manager (noscript) -->'
115+
sub_filter_once on;
116+
}
117+
proxy_cache static-cache;
118+
proxy_cache_valid 404 1m;
119+
proxy_cache_valid 200 10m;
120+
proxy_cache_use_stale error timeout updating http_404 http_500 http_502 http_503 http_504;
121+
proxy_cache_bypass $http_x_purge;
122+
proxy_cache_key $proxy_upstream_name$request_uri;
123+
proxy_cache_lock on;
124+
proxy_cache_use_stale updating;
125+
add_header X-Cache-Status $upstream_cache_status;
126+
spec:
127+
rules:
128+
- host: penn-chime.bus.phl.io
129+
http:
130+
paths:
131+
- path: /static/
132+
backend:
133+
serviceName: chime
134+
servicePort: 80
135+
- host: penn-chime-alt.bus.phl.io
136+
http:
137+
paths:
138+
- path: /static/
139+
backend:
140+
serviceName: chime
141+
servicePort: 80

0 commit comments

Comments
 (0)