-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
bf1545a
commit 68e8f2e
Showing
12 changed files
with
438 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
--- | ||
################################# | ||
################################# | ||
## Super Linter GitHub Actions ## | ||
################################# | ||
################################# | ||
name: Lint Code Base | ||
|
||
############################# | ||
# Start the job on all push # | ||
############################# | ||
on: | ||
push: | ||
branches-ignore: [master, main] | ||
# Remove the line above to run when pushing to master | ||
pull_request: | ||
branches: [master, main] | ||
|
||
############### | ||
# Set the Job # | ||
############### | ||
jobs: | ||
build: | ||
# Name the Job | ||
name: Lint Code Base | ||
# Set the agent to run on | ||
runs-on: ubuntu-latest | ||
|
||
################## | ||
# Load all steps # | ||
################## | ||
steps: | ||
########################## | ||
# Checkout the code base # | ||
########################## | ||
- name: Checkout Code | ||
uses: actions/checkout@v3 | ||
with: | ||
# Full git history is needed to get a proper | ||
# list of changed files within `super-linter` | ||
fetch-depth: 0 | ||
|
||
################################ | ||
# Run Linter against code base # | ||
################################ | ||
- name: Lint Code Base | ||
uses: github/super-linter@v4 | ||
env: | ||
VALIDATE_ALL_CODEBASE: false | ||
KUBERNETES_KUBEVAL_OPTIONS: --ignore-missing-schemas | ||
VALIDATE_PYTHON_MYPY: false | ||
DEFAULT_BRANCH: main | ||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
--- | ||
name: Release | ||
|
||
on: | ||
push: | ||
tags: | ||
- "*" | ||
|
||
jobs: | ||
release: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@v3 | ||
- name: Build and publish the container image for ${{ github.repository }}:${{ github.ref_name }} | ||
uses: macbre/push-to-ghcr@v12 | ||
with: | ||
image_name: ${{ github.repository }} | ||
github_token: ${{ secrets.GITHUB_TOKEN }} | ||
dockerfile: build/container/Dockerfile | ||
image_tag: ${{ github.ref_name }} | ||
- name: Build and publish the container image for ${{ github.repository }}:latest | ||
uses: macbre/push-to-ghcr@v12 | ||
with: | ||
image_name: ${{ github.repository }} | ||
github_token: ${{ secrets.GITHUB_TOKEN }} | ||
dockerfile: build/container/Dockerfile | ||
image_tag: latest | ||
- name: Create a Release | ||
uses: softprops/action-gh-release@v1 | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }} | ||
with: | ||
name: X K8Spin internal kubeconfig generator ${{ github.ref_name }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
IMAGE=internal-kubeconfig-generator | ||
|
||
lint: | ||
@docker run --rm -e RUN_LOCAL=true -e KUBERNETES_KUBEVAL_OPTIONS=--ignore-missing-schemas -e VALIDATE_PYTHON_MYPY=false -v $(shell pwd):/tmp/lint github/super-linter:v4 | ||
|
||
build-local: | ||
@docker build --no-cache --pull -t $(IMAGE):local . -f build/container/Dockerfile | ||
|
||
clean: | ||
@find . -name "*.pyc" -exec rm -f {} \; | ||
@find . -name "__pycache__" -exec rm -rf {} \; | ||
@rm -rf super-linter.log |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,105 @@ | ||
# internal-kubeconfig-generator | ||
Create dynamically a kubeconfig inside a secret with a kubeconfig from a serviceaccount | ||
# Internal kubeconfig generator | ||
|
||
This simple controller generates a `kubeconfig` and stores it in a `Secret` for each | ||
[`Secret` created in a specific namespace for a specific service account.](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#manually-create-a-long-lived-api-token-for-a-serviceaccount) | ||
|
||
## Warning | ||
|
||
**The project is currently under development and is not ready for production use.** | ||
|
||
## Motivation | ||
|
||
The main motivation for developing this controller is to enable the multi-tenancy feature of Crossplane. | ||
|
||
The crossplane kubernetes provider does not support the usage of `ServiceAccount`s resource yet to configure | ||
a `providerConfig`. Then, the only way to configure a `providerConfig` is to use a `Secret` with a `kubeconfig`. | ||
|
||
This is where this controller comes in. | ||
|
||
## How it works | ||
|
||
The controller watches for `Secret's` with a few specific annotations: | ||
|
||
- `kubernetes.io/service-account.name`: This is the required annotation to tell the kubernetes controller which `ServiceAccount` belongs to this `Secret`. | ||
- `x.k8spin.cloud/kubeconfig`: This is the trigger annotation to tell the controller to generate a `kubeconfig` for this `Secret`. | ||
|
||
The controller will generate a new `Secret` with the same name as the `ServiceAccount` defined in the `kubernetes.io/service-account.name` annotation ending with `-kubeconfig` suffix. | ||
|
||
## How to use it | ||
|
||
```bash | ||
$ kubectl apply -f https://raw.githubusercontent.com/angelbarrera92/internal-kubeconfig-generator/master/deploy/kubernetes/deploy.yaml | ||
namespace/k8spin-system created | ||
serviceaccount/internal-kubeconfig-generator created | ||
clusterrole.rbac.authorization.k8s.io/internal-kubeconfig-generator created | ||
clusterrolebinding.rbac.authorization.k8s.io/internal-kubeconfig-generator created | ||
deployment.apps/internal-kubeconfig-generator created | ||
$ kubectl wait --for=condition=available --timeout=600s deployment/internal-kubeconfig-generator -n k8spin-system | ||
deployment.apps/internal-kubeconfig-generator condition met | ||
``` | ||
|
||
### Demo | ||
|
||
```bash | ||
$ kubectl apply -f https://raw.githubusercontent.com/angelbarrera92/internal-kubeconfig-generator/master/hack/demo.yaml | ||
clusterrole.rbac.authorization.k8s.io/provider-kubernetes-view created | ||
clusterrolebinding.rbac.authorization.k8s.io/provider-kubernetes-view created | ||
serviceaccount/provider-kubernetes-view created | ||
secret/provider-kubernetes-view created | ||
``` | ||
|
||
This creates a set of resources: | ||
- A `ServiceAccount` named `provider-kubernetes-view` | ||
- [The `Secret` named `provider-kubernetes-view` that contains the `token` for the `ServiceAccount`.](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#manually-create-a-long-lived-api-token-for-a-serviceaccount) | ||
- `ClusterRole` and `ClusterRoleBinding` to allow the `ServiceAccount` to list the `Namespaces`. | ||
|
||
Then, as the `secret` named `provider-kubernetes-view` has the `x.k8spin.cloud/kubeconfig` annotation, the controller will generate a new `Secret` named `provider-kubernetes-view-kubeconfig` with the `kubeconfig` for the `ServiceAccount`. | ||
|
||
```bash | ||
$ kubectl get secret/provider-kubernetes-view-kubeconfig -o yaml | ||
apiVersion: v1 | ||
data: | ||
kubeconfig: <REDACTED> | ||
kind: Secret | ||
metadata: | ||
creationTimestamp: "2023-01-04T15:01:39Z" | ||
name: provider-kubernetes-view-kubeconfig | ||
namespace: default | ||
ownerReferences: | ||
- apiVersion: v1 | ||
kind: Secret | ||
name: provider-kubernetes-view | ||
uid: fe338cb5-ac4e-4c7f-9e5a-6b7c68216145 | ||
resourceVersion: "603" | ||
uid: 6c853730-ca5c-4e7d-bfdf-912e31b9c4ec | ||
type: Opaque | ||
``` | ||
|
||
#### Test | ||
|
||
Includes a `Job` that uses the generated `kubeconfig` to list the `Namespaces` in the cluster. | ||
|
||
```bash | ||
$ kubectl apply -f https://raw.githubusercontent.com/angelbarrera92/internal-kubeconfig-generator/master/hack/demo-test.yaml | ||
job.batch/list-namespaces created | ||
$ kubectl logs -f job/list-namespaces | ||
NAME STATUS AGE | ||
default Active 8m17s | ||
kube-system Active 8m17s | ||
kube-public Active 8m17s | ||
kube-node-lease Active 8m16s | ||
k8spin-system Active 7m43s | ||
``` | ||
|
||
## Development | ||
|
||
### Prerequisites | ||
|
||
- [python3](https://www.python.org/downloads/) | ||
- [virtualenv](https://virtualenv.pypa.io/en/latest/installation.html) | ||
- [docker](https://docs.docker.com/install/) | ||
|
||
|
||
## License | ||
|
||
[MIT](LICENSE) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# hadolint ignore=DL3007 | ||
FROM cgr.dev/chainguard/python:latest | ||
|
||
# Set the working directory to /home/nonroot | ||
WORKDIR /home/nonroot | ||
|
||
# Setup the virtual environment | ||
RUN ["/usr/bin/python3", "-m" , "venv", "--upgrade-deps", ".venv"] | ||
COPY requirements.txt requirements.txt | ||
RUN [".venv/bin/pip", "install", "--disable-pip-version-check", "-r", "requirements.txt"] | ||
|
||
# Copy the application | ||
COPY main.py main.py | ||
|
||
# Run the application | ||
ENTRYPOINT [".venv/bin/kopf", "run", "-A", "main.py"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
--- | ||
apiVersion: v1 | ||
kind: Namespace | ||
metadata: | ||
name: k8spin-system | ||
labels: | ||
app: k8spin.cloud | ||
--- | ||
apiVersion: v1 | ||
kind: ServiceAccount | ||
metadata: | ||
name: internal-kubeconfig-generator | ||
namespace: k8spin-system | ||
--- | ||
apiVersion: rbac.authorization.k8s.io/v1 | ||
kind: ClusterRole | ||
metadata: | ||
name: internal-kubeconfig-generator | ||
rules: | ||
# Allow to get, list and watch namespaces | ||
- apiGroups: [""] | ||
resources: ["namespaces"] | ||
verbs: ["get", "list", "watch"] | ||
# Allow to get, list and watch secrets | ||
- apiGroups: [""] | ||
resources: ["secrets"] | ||
verbs: ["get", "list", "watch", "create", "update", "patch"] | ||
# Allow to get, list and watch service accounts | ||
- apiGroups: [""] | ||
resources: ["serviceaccounts"] | ||
verbs: ["get", "list", "watch"] | ||
# Allow to get, list and watch customresourcedefinitions | ||
- apiGroups: ["apiextensions.k8s.io"] | ||
resources: ["customresourcedefinitions"] | ||
verbs: ["get", "list", "watch"] | ||
# Allow to post events | ||
- apiGroups: [""] | ||
resources: ["events"] | ||
verbs: ["create", "patch"] | ||
--- | ||
apiVersion: rbac.authorization.k8s.io/v1 | ||
kind: ClusterRoleBinding | ||
metadata: | ||
name: internal-kubeconfig-generator | ||
roleRef: | ||
apiGroup: rbac.authorization.k8s.io | ||
kind: ClusterRole | ||
name: internal-kubeconfig-generator | ||
subjects: | ||
- kind: ServiceAccount | ||
name: internal-kubeconfig-generator | ||
namespace: k8spin-system | ||
--- | ||
apiVersion: apps/v1 | ||
kind: Deployment | ||
metadata: | ||
labels: | ||
app: k8spin.cloud | ||
name: internal-kubeconfig-generator | ||
namespace: k8spin-system | ||
spec: | ||
selector: | ||
matchLabels: | ||
app: k8spin.cloud | ||
template: | ||
metadata: | ||
labels: | ||
app: k8spin.cloud | ||
spec: | ||
serviceAccountName: internal-kubeconfig-generator | ||
containers: | ||
- name: internal-kubeconfig-generator | ||
image: ghcr.io/angelbarrera92/internal-kubeconfig-generator:latest | ||
imagePullPolicy: Always |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
# Create a Kubernetes job that runs a kubectl command to list all namespaces | ||
# Use the kubeconfig that is inside the secret provider-kubernetes-view-kubeconfig in the kubeconfig key | ||
--- | ||
apiVersion: batch/v1 | ||
kind: Job | ||
metadata: | ||
name: list-namespaces | ||
namespace: default | ||
spec: | ||
template: | ||
spec: | ||
containers: | ||
- name: kubectl | ||
image: bitnami/kubectl:1.25 | ||
command: ["kubectl", "get", "ns", "--kubeconfig", "/kubeconfig/config"] | ||
volumeMounts: | ||
- name: kubeconfig | ||
mountPath: /kubeconfig | ||
readOnly: true | ||
volumes: | ||
- name: kubeconfig | ||
secret: | ||
secretName: provider-kubernetes-view-kubeconfig | ||
items: | ||
- key: kubeconfig | ||
path: config | ||
restartPolicy: Never | ||
backoffLimit: 4 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
--- | ||
# Create a clusterrole that allows to list namespaces | ||
apiVersion: rbac.authorization.k8s.io/v1 | ||
kind: ClusterRole | ||
metadata: | ||
name: provider-kubernetes-view | ||
rules: | ||
- apiGroups: [""] | ||
resources: ["namespaces"] | ||
verbs: ["get", "list", "watch"] | ||
--- | ||
# Create a clusterrolebinding that binds the clusterrole to the serviceaccount provider-kubernetes-view | ||
apiVersion: rbac.authorization.k8s.io/v1 | ||
kind: ClusterRoleBinding | ||
metadata: | ||
name: provider-kubernetes-view | ||
roleRef: | ||
apiGroup: rbac.authorization.k8s.io | ||
kind: ClusterRole | ||
name: provider-kubernetes-view | ||
subjects: | ||
- kind: ServiceAccount | ||
name: provider-kubernetes-view | ||
namespace: default | ||
--- | ||
apiVersion: v1 | ||
kind: ServiceAccount | ||
metadata: | ||
name: provider-kubernetes-view | ||
namespace: default | ||
--- | ||
apiVersion: v1 | ||
kind: Secret | ||
metadata: | ||
name: provider-kubernetes-view | ||
namespace: default | ||
annotations: | ||
kubernetes.io/service-account.name: provider-kubernetes-view | ||
x.k8spin.cloud/kubeconfig: "" | ||
type: kubernetes.io/service-account-token |
Oops, something went wrong.