Skip to content

Commit 523ec01

Browse files
authored
Merge pull request #2 from dilyar85/open-source
Add project
2 parents 87e158c + c7df393 commit 523ec01

File tree

3,522 files changed

+1161286
-5
lines changed

Some content is hidden

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

3,522 files changed

+1161286
-5
lines changed

.gitignore

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Binaries for programs and plugins
2+
/kube-exec-controller
3+
/kubectl-pi
4+
5+
# Test binary, built with `go test -c`
6+
*.test
7+
8+
# Output of the go coverage tool, specifically when used with LiteIDE
9+
*.out
10+
11+
# Local development files
12+
.DS_Store
13+
.idea/*
14+
.vscode
15+
16+
# CSR related tools and files
17+
/cfssl
18+
/cfssljson
19+
server-key.pem
20+
server.crt
21+
server.csr
22+
23+
# Ensure no vendor files get ignored
24+
!vendor/**

.travis.yml

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
language: go
2+
go:
3+
- 1.16
4+
script:
5+
- make test-unit
6+
- .travis/check_workspace.sh

.travis/check_workspace.sh

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/bin/sh
2+
set -e
3+
4+
if [ "$(git status --porcelain | wc -l)" -ne "0" ]; then
5+
echo "Unclean workspace detected. This typically indicates 'gofmt' changed some files." \
6+
"\n Please run 'make fmt' locally to verify."
7+
exit 1
8+
else
9+
exit 0
10+
fi

CONTRIBUTING.md

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# Contributing
2+
All contributions are welcome to this project.
3+
4+
## Contributor License Agreement
5+
Before a contribution can be merged into this project, please fill out the Contributor License Agreement (CLA) located at:
6+
7+
https://cla-assistant.io/box/cla
8+
9+
To learn more about CLAs and why they are important to open source projects, please see the [Wikipedia entry](http://en.wikipedia.org/wiki/Contributor_License_Agreement).
10+
11+
## Code of Conduct
12+
This project adheres to the [Box Open Code of Conduct](http://opensource.box.com/code-of-conduct/). By participating, you are expected to uphold this code.
13+
14+
## How to contribute
15+
* **File an issue** - if you found a bug, want to request an enhancement, or want to implement something (bug fix or feature).
16+
* **Send a pull request** - if you want to contribute code. Please be sure to file an issue first.
17+
18+
## Pull request best practices
19+
We want to accept your pull requests. Please follow these steps:
20+
21+
### Step 1: File an issue
22+
Before writing any code, please file an issue stating the problem you want to solve or the feature you want to implement. This allows us to give you feedback before you spend any time writing code. There may be a known limitation that can't be addressed, or a bug that has already been fixed in a different way. The issue allows us to communicate and figure out if it's worth your time to write a bunch of code for the project.
23+
24+
### Step 2: Fork this repository in GitHub
25+
This will create your own copy of our repository.
26+
27+
### Step 3: Add the upstream source
28+
The upstream source is the project under the Box organization on GitHub. To add an upstream source for this project, type:
29+
30+
```
31+
$ git remote add upstream [email protected]:box/kube-exec-controller.git
32+
```
33+
34+
This will come in useful later.
35+
36+
### Step 4: Create a feature branch
37+
Create a branch with a descriptive name, such as `add-search`.
38+
39+
### Step 5: Push your feature branch to your fork
40+
As you develop code, continue to push code to your remote feature branch. Please make sure to include the issue number you're addressing in your commit message, such as:
41+
42+
```
43+
$ git commit -m "Adding search (fixes #123)"
44+
```
45+
46+
This helps us out by allowing us to track which issue your commit relates to.
47+
48+
Keep a separate feature branch for each issue you want to address.
49+
50+
### Step 6: Rebase
51+
Before sending a pull request, rebase against upstream, such as:
52+
53+
```
54+
$ git fetch upstream
55+
$ git rebase upstream/main
56+
```
57+
58+
This will add your changes on top of what's already in upstream, minimizing merge issues.
59+
60+
### Step 7: Run the tests
61+
Make sure that [all tests are passing](https://app.travis-ci.com/github/box/kube-exec-controller) before submitting a pull request (required for merging any new PRs). You can also run `make test-unit` locally to execute these tests.
62+
63+
Coverage is lacking on the more integration-heavy components, including:
64+
* Receiving admission requests from K8s API-Server
65+
* Evicting Pods with potentially mutated container
66+
* Interacting with commands from kubectl-pi plugin
67+
68+
Until better automated testing of these components is implemented, we expect thorough local testing to ensure that the kube-exec-controller container is still fully functional. You can deploy the app and verify its functionality by:
69+
* Run `make deploy` to apply the app and enable admission control
70+
* Check if the updated kube-exec-controller Pod is up running
71+
* Run `kubectl exec` to a random Pod and verify if the Pod gets evicted
72+
* Run `kubectl pi get/extend` to verify if the commands get handled by kube-exec-controller as expected (see the Install section in [README](README.md) for more detail)
73+
74+
### Step 8: Send the pull request
75+
Send the pull request from your feature branch to us. Be sure to include a description that lets us know what work you did.
76+
77+
Keep in mind that we like to see one issue addressed per pull request, as this helps keep our git history clean and we can more easily track down issues.

Dockerfile

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
ARG APP_NAME="kube-exec-controller"
2+
3+
FROM golang:1.16 as builder
4+
ARG APP_NAME
5+
WORKDIR /build
6+
COPY . .
7+
RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -mod vendor -o ${APP_NAME} cmd/${APP_NAME}/main.go
8+
9+
FROM alpine
10+
ARG APP_NAME
11+
LABEL com.box.name=${APP_NAME}
12+
LABEL maintainer="[email protected]"
13+
COPY --from=builder /build/${APP_NAME} /
14+
RUN chmod +x /${APP_NAME}

Makefile

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
ENVVAR = GOOS=linux GOARCH=amd64
2+
APP_NAME = kube-exec-controller
3+
PLUGIN_NAME = kubectl-pi
4+
5+
clean:
6+
rm -rf $(APP_NAME)
7+
rm -rf $(PLUGIN_NAME)
8+
9+
fmt:
10+
find . -path ./vendor -prune -o -name '*.go' -print | xargs -L 1 -I % gofmt -s -w %
11+
12+
test-unit: clean fmt
13+
CGO_ENABLED=0 go test -v -cover ./...
14+
15+
build-cgo: clean fmt
16+
$(ENVVAR) CGO_ENABLED=1 go build -mod vendor -o $(APP_NAME) cmd/$(APP_NAME)/main.go
17+
$(ENVVAR) CGO_ENABLED=1 go build -mod vendor -o $(PLUGIN_NAME) cmd/$(PLUGIN_NAME)/main.go
18+
19+
build: clean fmt
20+
$(ENVVAR) CGO_ENABLED=0 go build -mod vendor -o $(APP_NAME) cmd/$(APP_NAME)/main.go
21+
$(ENVVAR) CGO_ENABLED=0 go build -mod vendor -o $(PLUGIN_NAME) cmd/$(PLUGIN_NAME)/main.go
22+
23+
container: clean fmt
24+
docker build -f Dockerfile -t $(APP_NAME):local .
25+
26+
deploy: container
27+
kind load docker-image $(APP_NAME):local
28+
# build the kubectl-pi plugin (to use it from your Mac)
29+
rm -rf $(PLUGIN_NAME)
30+
env GOOS=darwin GOARCH=amd64 go build -mod vendor -o $(PLUGIN_NAME) cmd/$(PLUGIN_NAME)/main.go
31+
export PATH="$(PWD):$(PATH)"
32+
./demo/deploy.sh
33+
34+
.PHONY: clean fmt test-unit build-cgo build container deploy

README.md

+141-5
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,149 @@
1+
# kube-exec-controller
2+
[![Project Status](https://opensource.box.com/badges/active.svg)](https://opensource.box.com/badges)
3+
[![Build Status](https://app.travis-ci.com/box/kube-exec-controller.svg?branch=main)](https://app.travis-ci.com/box/kube-exec-controller)
4+
[![Go Report Card](https://goreportcard.com/badge/github.com/box/kube-exec-controller)](https://goreportcard.com/report/github.com/box/kube-exec-controller)
5+
6+
kube-exec-controller is an [admission controller](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/) for handling container drift (caused by kubectl `exec`, `attach`, `cp`, or other interactive requests) inside a Kubernetes cluster. It runs as a Deployment and can be referred in a `ValidatingWebhookConfiguration` (see the provided [demo/](demo/) as an example) to detect and evict interacted Pods after a pre-defined interval. This project also includes a [kubectl plugin](https://kubernetes.io/docs/tasks/extend-kubectl/kubectl-plugins/), named `kubectl-pi` (*pod-interaction*), for checking such interacted Pods or extending their eviction time.
7+
8+
Here is an overview of running a `kubectl exec` command in a K8s cluster with this admission controller service enabled:
9+
10+
![workflow-diagram](workflow-diagram.png)
11+
12+
## Install
13+
#### Prerequisite
14+
- [Docker (17.05+)](https://www.docker.com/get-started)
15+
- [Kubernetes (1.16+)](https://kubernetes.io/)
16+
- [Kind (for local development only)](https://kind.sigs.k8s.io/)
17+
18+
If you have a local K8s cluster up running, you can deploy kube-exec-controller and apply its validating admission webhooks simply by:
19+
```
20+
$ git clone [email protected]:box/kube-exec-controller.git
21+
$ cd kube-exec-controller
22+
$ make deploy
23+
```
24+
25+
You should get a demo app and its admission webhooks deployed after the above `make deploy` command completes:
26+
```
27+
$ kubectl get pod,service -n kube-exec-controller
28+
NAME READY STATUS RESTARTS AGE
29+
pod/demo-deploy-5d5cd95f94-jwf5b 1/1 Running 0 9s
30+
31+
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
32+
service/demo-service ClusterIP 10.96.211.63 <none> 443/TCP 9s
33+
34+
$ kubectl get ValidatingWebhookConfiguration
35+
NAME WEBHOOKS AGE
36+
demo-validating-webhook-config 2 24s
37+
```
38+
39+
To see how kube-exec-controller works, let's create a test Pod in your local cluster and send a `kubectl exec` request to it:
40+
```
41+
$ kubectl run test --image=nginx
42+
pod/test created
43+
44+
$ kubectl exec test -- touch new-file
45+
```
46+
47+
You will see the test Pod has some labels attached and receives corresponding K8s events from our controller app:
48+
```
49+
$ kubectl get pod --show-labels
50+
NAME READY STATUS RESTARTS AGE LABELS
51+
test 1/1 Running 0 2s box.com/podInitialInteractionTimestamp=1634408037,box.com/podInteractorUsername=kubernetes-admin,box.com/podTTLDuration=2m0s,run=test
52+
53+
$ kubectl describe pod test
54+
...
55+
Warning PodInteraction 20s kube-exec-controller Pod was interacted with 'kubectl exec/attach' command by a user 'kubernetes-admin' initially at time 2021-10-16 18:04:44.5257517 +0000 UTC m=+27.185038701
56+
Warning PodInteraction 21s kube-exec-controller Pod will be evicted at time 2021-10-16 18:06:44 +0000 UTC (in about 1m59s)
57+
```
58+
59+
You can also utilize the `kubectl pi` plugin to get more detailed info or request an extension to the test Pod's eviction time:
60+
```
61+
$ kubectl pi get
62+
POD_NAME INTERACTOR POD_TTL EXTENSION EXTENSION_REQUESTER EVICTION_TIME
63+
test kubernetes-admin 2m0s 2021-10-16 18:06:44 +0000 UTC
64+
65+
$ kubectl pi extend --duration=1m
66+
Successfully extended the termination time of pod/test with a duration=1m
67+
68+
$ kubectl pi get
69+
POD_NAME INTERACTOR POD_TTL EXTENSION EXTENSION_REQUESTER EVICTION_TIME
70+
test kubernetes-admin 2m0s 1m kubernetes-admin 2021-10-16 18:07:44 +0000 UTC
71+
72+
$ kubectl describe pod test
73+
...
74+
Warning PodInteraction 30s kube-exec-controller Pod eviction time has been extended by '1m', as requested from user 'kubernetes-admin'. New eviction time: 2021-10-16 18:07:44 +0000 UTC
75+
Warning PodInteraction 30s kube-exec-controller Pod will be evicted at time 2021-10-16 18:07:44 +0000 UTC (in about 2m21s)
76+
```
77+
78+
## Usage
79+
#### kube-exec-controller
80+
```
81+
$ kube-exec-controller --help
82+
Usage of kube-exec-controller:
83+
-api-server string
84+
URL to K8s api-server, required if kube-proxy is not set up
85+
-cert-path string
86+
Path to the PEM-encoded TLS certificate
87+
-extend-chan-size int
88+
Buffer size of the channel for handling Pod extension (default 500)
89+
-interact-chan-size int
90+
Buffer size of the channel for handling Pod interaction (default 500)
91+
-key-path string
92+
Path to the un-encrypted TLS key
93+
-log-level debug
94+
Log level. debug, `info`, `warn`, `error` are currently supported (default "info")
95+
-namespace-allowlist string
96+
Comma separated list of namespaces that allow interaction without evicting their Pods
97+
-port int
98+
Port for the app to listen on (default 8443)
99+
-ttl-seconds int
100+
TTL (time-to-live) of interacted Pods before getting evicted by the controller (default 600)
101+
```
102+
103+
#### kubectl-pi
104+
```
105+
$ kubectl pi --help
106+
Get pod interaction info or request an extension of its termination time
107+
108+
Usage:
109+
kubectl pi [command] [flags]
110+
111+
Examples:
112+
113+
# get interaction info of specified pod(s)
114+
kubectl pi get <pod-name-1> <pod-name-2> <...> -n POD_NAMESPACE
115+
116+
# get interaction info of all pods under the given namespace
117+
kubectl pi get -n <pod-namespace> --all
118+
119+
# extend termination time of interacted pod(s)
120+
kubectl pi extend -d <duration> <pod-name-1> <pod-name-2> <...> -n POD_NAMESPACE
121+
122+
# extend termination time of all interacted pods under the given namespace
123+
kubectl pi extend -d <duration> -n <pod-namespace> --all
124+
125+
Flags:
126+
-a, --all if present, select all pods under specified namespace (and ignore any given pod podName)
127+
--cluster string The name of the kubeconfig cluster to use
128+
--context string The name of the kubeconfig context to use
129+
-d, --duration string a relative duration such as 5s, 2m, or 3h, default to 30m (default "30m")
130+
-h, --help help for kubectl
131+
-n, --namespace string If present, the namespace scope for this CLI request
132+
...
133+
```
134+
135+
## Contribution
136+
Refer to [CONTRIBUTING.md](CONTRIBUTING.md)
137+
1138
## Copyright and License
2-
3-
Copyright 2015 Box, Inc. All rights reserved.
4-
139+
Copyright 2021 Box, Inc. All rights reserved.
140+
5141
Licensed under the Apache License, Version 2.0 (the "License");
6142
you may not use this file except in compliance with the License.
7143
You may obtain a copy of the License at
8-
144+
9145
http://www.apache.org/licenses/LICENSE-2.0
10-
146+
11147
Unless required by applicable law or agreed to in writing, software
12148
distributed under the License is distributed on an "AS IS" BASIS,
13149
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

0 commit comments

Comments
 (0)