diff --git a/README.md b/README.md index 5008ea5..beaea23 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,22 @@ A project to store container-based hosting stuff. - [Jellyfin](#jellyfin) - [Iperf3](#iperf3) - [Upgrading](#upgrading) + - [Create a Userspace](#create-a-userspace) + - [Quickstart](#quickstart) + - [Userspace](#userspace) + - [Namespace](#namespace) + - [Roles](#roles) + - [Rolebinding](#rolebinding) + - [Manual Steps](#manual-steps) + - [Create a kubernetes certsigner pod](#create-a-kubernetes-certsigner-pod) + - [Create the certsigner secret](#create-the-certsigner-secret) + - [Set up the certsigner pod](#set-up-the-certsigner-pod) + - [Generate a cert](#generate-a-cert) + - [Create a new Userspace](#create-a-new-userspace) + - [Sign the cert](#sign-the-cert) + - [Add to the config](#add-to-the-config) + - [Delete](#delete) + - [Signing a user cert - detailed notes](#signing-a-user-cert---detailed-notes) - [Help](#help) - [Troubleshooting](#troubleshooting) @@ -620,6 +636,217 @@ mv k3s /usr/local/bin/k3s systemctl start k3s ``` +## Create a Userspace + +This creates a user, namespace, and permissions with a simple script. + +### Quickstart + +```bash +# Create certsigner pod for all other operations +./setup.sh + +# Create a user, use "admin" to create an admin user +./adduser + +# Create a namespace and allow to access it +./createprojectspace + +# Update a project namespace with the contents of ./namespace +./updateprojectspace + +# Remove a user, their namespace, and their access +./removeuserspace +``` + +### Userspace + +#### Namespace + +```yaml +apiVersion: v1 +kind: Namespace +metadata: + name: {{ .Release.Name }} +``` + +#### Roles + +```yaml +kind: Role +apiVersion: rbac.authorization.k8s.io/v1beta1 +metadata: + name: namespace-manager + namespace: {{ .Release.Name }} +rules: +- apiGroups: + - "" + - extensions + - apps + - batch + - autoscaling + - networking.k8s.io + - traefik.containo.us + - rbac.authorization.k8s.io + - metrics.k8s.io + resources: + - deployments + - replicasets + - pods + - pods/exec + - pods/log + - pods/attach + - daemonsets + - statefulsets + - replicationcontrollers + - horizontalpodautoscalers + - services + - ingresses + - persistentvolumeclaims + - jobs + - cronjobs + - secrets + - configmaps + - serviceaccounts + - rolebindings + - ingressroutes + - middlewares + - endpoints + verbs: + - "*" +- apiGroups: + - "" + - metrics.k8s.io + - rbac.authorization.k8s.io + resources: + - resourcequotas + - roles + verbs: + - list +``` + +#### Rolebinding + +```yaml +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1beta1 +metadata: + namespace: {{ .Release.Name }} + name: namespace-manager +subjects: +- kind: User + name: {{ .Release.Name }} + apiGroup: "" +roleRef: + kind: ClusterRole + name: namespace-manager + apiGroup: "" +``` + +### Manual Steps + +#### Create a kubernetes certsigner pod + +This keeps the client-ca crt and key secret and allows the cert to be signed and stored on the pod + +#### Create the certsigner secret + +```bash +kubectl -n kube-system create secret generic certsigner --from-file /var/lib/rancher/k3s/server/tls/client-ca.crt --from-file /var/lib/rancher/k3s/server/tls/client-ca.key +``` + +#### Set up the certsigner pod + +```bash +scp certsigner.yaml :~/certsigner.yaml +kubectl apply -f certsigner.yaml +``` + +#### Generate a cert + +```bash +export USER= +docker run -it -v $(pwd)/users/$USER:/$USER python:latest openssl genrsa -out /$USER/$USER.key 2048 +docker run -it -v $(pwd)/users/$USER:/$USER python:latest openssl req -new -key /$USER/$USER.key -out /$USER/$USER.csr -subj "/CN=$USER/O=user" +``` + +#### Create a new Userspace + +```bash +helm template $USER ./namespace | kubectl --context admin apply -f - +``` + +#### Sign the cert + +```bash +export USER= +kubectl --context admin cp $(pwd)/users/$USER/$USER.csr certsigner:/certs/$USER.csr +kubectl --context admin exec -it --context admin certsigner -- openssl x509 -in /certs/$USER.csr -req -CA /keys/client-ca.crt -CAkey /keys/client-ca.key -CAcreateserial -out /certs/$USER.crt -days 5000 +kubectl --context admin cp certsigner:/certs/$USER.crt $(pwd)/users/$USER/$USER.crt +``` + +#### Add to the config + +```bash +kubectl config set-credentials $USER --client-certificate=$USER.crt --client-key=$USER.key +kubectl config set-context $USER --cluster=mainframe --namespace=$USER --user=$USER +``` + +#### Delete + +```bash +kubectl config delete-context $USER +helm template $USER ./namespace | kubectl --context admin delete -f - +``` + +### Signing a user cert - detailed notes + +NOTE: ca.crt and ca.key are in /var/lib/rancher/k3s/server/tls/client-ca.* + +```bash +# First we create the credentials +# /CN= - the user +# /O= - the group + +# Navigate to the user directory +export USER= +cd $USER + +# Generate a private key +openssl genrsa -out $USER.key 2048 +# Check the key +# openssl pkey -in ca.key -noout -text +# Generate and send me the CSR +# The "user" group is my default group +openssl req -new -key $USER.key -out $USER.csr -subj "/CN=$USER/O=user" + +# Check the CSR +# openssl req -in $USER.csr -noout -text +# If satisfactory, sign the CSR +# Copy from /var/lib/rancher/k3s/server/tls/client-ca.crt and client-ca.key +openssl x509 -req -in $USER.csr -CA ../client-ca.crt -CAkey ../client-ca.key -CAcreateserial -out $USER.crt -days 5000 +# Review the certificate +# openssl x509 -in $USER.crt -text -noout + +# Send back the crt +# cp $USER.crt $USER.key ../server-ca.crt ~/.kube/ +kubectl config set-credentials $USER --client-certificate=$USER.crt --client-key=$USER.key +kubectl config set-context $USER --cluster=mainframe --namespace=$USER --user=$USER + +# Now we create the namespace, rolebindings, and resource quotas +# kubectl apply -f k8s/ + +# Add the cluster +# CA file can be found at https://3.14.3.100:6443/cacerts +- cluster: + certificate-authority: server-ca.crt + server: https://3.14.3.100:6443 + name: mainframe + +# Test if everything worked +kubectl --context=$USER-context get pods +``` + ## Help ### Troubleshooting diff --git a/certsigner.yaml b/certsigner.yaml new file mode 100755 index 0000000..d22ff18 --- /dev/null +++ b/certsigner.yaml @@ -0,0 +1,39 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: certsigner + namespace: kube-system +spec: + replicas: 1 + selector: + matchLabels: + app: certsigner + template: + metadata: + labels: + app: certsigner + spec: + containers: + - name: certsigner + image: python:latest + command: ["cat"] + tty: true + resources: + requests: + memory: 1Mi + cpu: 1m + limits: + memory: 100Mi + cpu: 100m + volumeMounts: + - mountPath: /keys + name: keys + - mountPath: /certs + name: certs + volumes: + - name: keys + secret: + secretName: certsigner + - name: certs + emptyDir: {} + restartPolicy: Always diff --git a/cluster-readonly.yaml b/cluster-readonly.yaml new file mode 100755 index 0000000..8e04fc6 --- /dev/null +++ b/cluster-readonly.yaml @@ -0,0 +1,30 @@ +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: cluster-readonly +rules: +- apiGroups: + - "" + - rbac.authorization.k8s.io + - storage.k8s.io + - networking.k8s.io + - traefik.containo.us + resources: + - storageclasses + verbs: + - list + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: cluster-readonly +subjects: +- kind: Group + name: user + apiGroup: "" +roleRef: + kind: ClusterRole + name: cluster-readonly + apiGroup: "" diff --git a/clusterrole.yaml b/clusterrole.yaml new file mode 100755 index 0000000..8607392 --- /dev/null +++ b/clusterrole.yaml @@ -0,0 +1,16 @@ +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: user-readonly +rules: +- apiGroups: + - rbac.authorization.k8s.io + - storage.k8s.io + - networking.k8s.io + resources: + - clusterroles + - storageclasses + - ingressclasses + verbs: + - list + - watch diff --git a/helm/namespace/.helmignore b/helm/namespace/.helmignore new file mode 100755 index 0000000..0e8a0eb --- /dev/null +++ b/helm/namespace/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/helm/namespace/Chart.yaml b/helm/namespace/Chart.yaml new file mode 100755 index 0000000..ffc3e5c --- /dev/null +++ b/helm/namespace/Chart.yaml @@ -0,0 +1,23 @@ +apiVersion: v2 +name: namespace +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.0.1 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +appVersion: 1.16.0 diff --git a/helm/namespace/README.md b/helm/namespace/README.md new file mode 100755 index 0000000..35a6f6e --- /dev/null +++ b/helm/namespace/README.md @@ -0,0 +1,211 @@ +# Project Userspace + +## One provisioner to rule them all + +### Quickstart + +1. Start Docker +2. Run createprojectspace.sh + +```bash +./createprojectspace.sh +``` + +### Update a user + +```bash +export USER=user +helm template $USER ./namespace | kubectl --context admin apply -f - +``` + +### Objectives + +1. Provision a namespace with clusterroles, rolebindings, and a dedicated nfs-provisioner with one helm chart +2. Create an easy way for users to sign their certificates +3. Create a cleanup script without deleting user data +4. profit + +### Userspace + +#### Namespace + +```yaml +apiVersion: v1 +kind: Namespace +metadata: + name: {{ .Release.Name }} +``` + +#### Roles + +```yaml +kind: Role +apiVersion: rbac.authorization.k8s.io/v1beta1 +metadata: + name: namespace-manager + namespace: {{ .Release.Name }} +rules: +- apiGroups: + - "" + - extensions + - apps + - batch + - autoscaling + - networking.k8s.io + - traefik.containo.us + - rbac.authorization.k8s.io + - metrics.k8s.io + resources: + - deployments + - replicasets + - pods + - pods/exec + - pods/log + - pods/attach + - daemonsets + - statefulsets + - replicationcontrollers + - horizontalpodautoscalers + - services + - ingresses + - persistentvolumeclaims + - jobs + - cronjobs + - secrets + - configmaps + - serviceaccounts + - rolebindings + - ingressroutes + - middlewares + - endpoints + verbs: + - "*" +- apiGroups: + - "" + - metrics.k8s.io + - rbac.authorization.k8s.io + resources: + - resourcequotas + - roles + verbs: + - list +``` + +#### Rolebinding + +```yaml +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1beta1 +metadata: + namespace: {{ .Release.Name }} + name: namespace-manager +subjects: +- kind: User + name: {{ .Release.Name }} + apiGroup: "" +roleRef: + kind: ClusterRole + name: namespace-manager + apiGroup: "" +``` + +### Create a kubernetes certsigner pod + +This keeps the client-ca crt and key secret and allows the cert to be signed and stored on the pod + +#### Create the certsigner secret + +```bash +kubectl -n kube-system create secret generic certsigner --from-file /var/lib/rancher/k3s/server/tls/client-ca.crt --from-file /var/lib/rancher/k3s/server/tls/client-ca.key +``` + +#### Set up the certsigner pod + +```bash +kubectl --context admin apply -f certsigner +``` + +#### Generate a cert + +```bash +export USER= +docker run -it -v $(pwd)/users/$USER:/$USER python:latest openssl genrsa -out /$USER/$USER.key 2048 +docker run -it -v $(pwd)/users/$USER:/$USER python:latest openssl req -new -key /$USER/$USER.key -out /$USER/$USER.csr -subj "/CN=$USER/O=user" +``` + +#### Create a new Userspace + +```bash +helm template $USER ./namespace | kubectl --context admin apply -f - +``` + +#### Sign the cert + +```bash +export USER= +kubectl --context admin cp $(pwd)/users/$USER/$USER.csr certsigner:/certs/$USER.csr +kubectl --context admin exec -it --context admin certsigner -- openssl x509 -in /certs/$USER.csr -req -CA /keys/client-ca.crt -CAkey /keys/client-ca.key -CAcreateserial -out /certs/$USER.crt -days 5000 +kubectl --context admin cp certsigner:/certs/$USER.crt $(pwd)/users/$USER/$USER.crt +``` + +#### Add to the config + +```bash +kubectl config set-credentials $USER --client-certificate=$USER.crt --client-key=$USER.key +kubectl config set-context $USER --cluster=mainframe --namespace=$USER --user=$USER +``` + +#### Delete + +```bash +kubectl config delete-context $USER +helm template $USER ./namespace | kubectl --context admin delete -f - +``` + +### Signing a user cert - detailed notes + +NOTE: ca.crt and ca.key are in /var/lib/rancher/k3s/server/tls/client-ca.* + +```bash +# First we create the credentials +# /CN= - the user +# /O= - the group + +# Navigate to the user directory +export USER= +cd $USER + +# Generate a private key +openssl genrsa -out $USER.key 2048 +# Check the key +# openssl pkey -in ca.key -noout -text +# Generate and send me the CSR +# The "user" group is my default group +openssl req -new -key $USER.key -out $USER.csr -subj "/CN=$USER/O=user" + +# Check the CSR +# openssl req -in $USER.csr -noout -text +# If satisfactory, sign the CSR +# Copy from /var/lib/rancher/k3s/server/tls/client-ca.crt and client-ca.key +openssl x509 -req -in $USER.csr -CA ../client-ca.crt -CAkey ../client-ca.key -CAcreateserial -out $USER.crt -days 5000 +# Review the certificate +# openssl x509 -in $USER.crt -text -noout + +# Send back the crt +# cp $USER.crt $USER.key ../server-ca.crt ~/.kube/ +kubectl config set-credentials $USER --client-certificate=$USER.crt --client-key=$USER.key +kubectl config set-context $USER --cluster=mainframe --namespace=$USER --user=$USER + +# Now we create the namespace, rolebindings, and resource quotas +# kubectl apply -f k8s/ + +# Add the cluster +# CA file can be found at https://3.14.3.100:6443/cacerts +- cluster: + certificate-authority: server-ca.crt + server: https://3.14.3.100:6443 + name: mainframe + +# Test if everything worked +kubectl --context=$USER-context get pods +``` diff --git a/helm/namespace/templates/limitrange.yaml b/helm/namespace/templates/limitrange.yaml new file mode 100755 index 0000000..0df775d --- /dev/null +++ b/helm/namespace/templates/limitrange.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: LimitRange +metadata: + name: default + namespace: {{ .Release.Name }} +spec: + limits: + - type: Container + default: + memory: 128Mi + cpu: 100m + defaultRequest: + memory: 1Mi + cpu: 1m diff --git a/helm/namespace/templates/namespace.yaml b/helm/namespace/templates/namespace.yaml new file mode 100755 index 0000000..770073e --- /dev/null +++ b/helm/namespace/templates/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: {{ .Release.Name }} \ No newline at end of file diff --git a/helm/namespace/templates/resourcequota.yaml b/helm/namespace/templates/resourcequota.yaml new file mode 100755 index 0000000..3dad73e --- /dev/null +++ b/helm/namespace/templates/resourcequota.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: ResourceQuota +metadata: + name: default + namespace: {{ .Release.Name }} +spec: + hard: + requests.cpu: "8" + requests.memory: "8Gi" + limits.cpu: "16" + limits.memory: "16Gi" + requests.storage: "500Gi" diff --git a/helm/namespace/templates/role.yaml b/helm/namespace/templates/role.yaml new file mode 100755 index 0000000..6b494dd --- /dev/null +++ b/helm/namespace/templates/role.yaml @@ -0,0 +1,104 @@ +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: namespace-manager + namespace: {{ .Release.Name }} +rules: +- apiGroups: + - "" + - extensions + - apps + - batch + - autoscaling + - networking.k8s.io + - rbac.authorization.k8s.io + - metrics.k8s.io + - policy + - cert-manager.io + resources: + - deployments + - replicasets + - pods + - pods/exec + - pods/log + - pods/attach + - daemonsets + - statefulsets + - replicationcontrollers + - horizontalpodautoscalers + - services + - ingresses + - persistentvolumeclaims + - jobs + - cronjobs + - secrets + - configmaps + - serviceaccounts + - rolebindings + - ingressroutes + - middlewares + - endpoints + - deployments/scale + - poddisruptionbudgets + - certificates + - roles + verbs: + - "*" +- apiGroups: + - "" + - metrics.k8s.io + - rbac.authorization.k8s.io + - policy + resources: + - resourcequotas + - roles + verbs: + - list + - get +--- +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: namespace-readonly + namespace: {{ .Release.Name }} +rules: +- apiGroups: + - "" + - extensions + - apps + - batch + - autoscaling + - networking.k8s.io + - traefik.containo.us + - rbac.authorization.k8s.io + - metrics.k8s.io + - storage.k8s.io + resources: + - deployments + - replicasets + - pods + - pods/exec + - pods/log + - pods/attach + - daemonsets + - statefulsets + - replicationcontrollers + - horizontalpodautoscalers + - services + - ingresses + - persistentvolumeclaims + - jobs + - cronjobs + - secrets + - configmaps + - serviceaccounts + - rolebindings + - ingressroutes + - middlewares + - resourcequotas + - roles + - endpoints + - clusterroles + verbs: + - list + - watch diff --git a/helm/namespace/templates/rolebinding.yaml b/helm/namespace/templates/rolebinding.yaml new file mode 100755 index 0000000..66cfd9f --- /dev/null +++ b/helm/namespace/templates/rolebinding.yaml @@ -0,0 +1,26 @@ +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: namespace-manager + namespace: {{ .Release.Name }} +subjects: +- kind: User + name: {{ .Values.user }} + apiGroup: "" +roleRef: + kind: Role + name: namespace-manager + apiGroup: "" +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: user-readonly +subjects: +- kind: User + name: {{ .Values.user }} + apiGroup: "" +roleRef: + kind: ClusterRole + name: user-readonly + apiGroup: "" diff --git a/helm/namespace/values.yaml b/helm/namespace/values.yaml new file mode 100755 index 0000000..7c38eaa --- /dev/null +++ b/helm/namespace/values.yaml @@ -0,0 +1 @@ +user: admin \ No newline at end of file diff --git a/scripts/adduser.sh b/scripts/adduser.sh new file mode 100755 index 0000000..34f5e8c --- /dev/null +++ b/scripts/adduser.sh @@ -0,0 +1,135 @@ +#!/bin/bash + +# Use +# ./adduser.sh + +export SERVER=$1 +export USER=$2 + +export CERT_DIR=$HOME/.kube/$SERVER/users/$USER +export CA_CERT_DIR=$HOME/.kube/$SERVER + +export SERVER_USER_DIR="~/.kube/users/$USER" +export SERVER_NAME=$(echo "$SERVER" | sed 's/\./-/g') +export SERVER_USER="$USER-$SERVER_NAME" + +export KUBECONFIG="$HOME/.kube/$USER-config" + +if [ -z $USER ]; then +echo "No arguments supplied! Format is ./adduser.sh " +exit 1 +fi + +if [ -z $SERVER ]; then +echo "No server supplied for user $USER" +exit 1 +fi + +if [ $USER = "admin" ]; then +echo "Creating admin user for server $SERVER" +fi + +echo "Creating cert dir" +mkdir -p $CERT_DIR + +if [ $? -ne 0 ]; then + echo "Couldn't create cert dir at $CERT_DIR" + exit 1 +fi + +echo "Generating openssl cert" +docker run -u $UID -it -v $CERT_DIR:/$USER python:latest openssl genrsa -out /$USER/$USER.key 2048 + +if [ $USER = "admin" ]; then +docker run -u $UID -it -v $CERT_DIR:/$USER python:latest openssl req -new -key /$USER/$USER.key -out /$USER/$USER.csr -subj "/CN=$USER/O=system:masters" +else +docker run -u $UID -it -v $CERT_DIR:/$USER python:latest openssl req -new -key /$USER/$USER.key -out /$USER/$USER.csr -subj "/CN=$USER/O=user" +fi +# /CN=admin/O=manager + +if [ $? -ne 0 ]; then + echo "Couldn't create cert with Docker. Are you sure it's running?" + exit 1 +fi + +echo "Creating namespace dir on server" +ssh $SERVER "mkdir -p $SERVER_USER_DIR" +echo "Copying client csr to server cert dir" +scp $CERT_DIR/$USER.csr $SERVER:$SERVER_USER_DIR/$USER.csr + +if [ $? -ne 0 ]; then + echo "Failed to copy client csr to server cert dir" + exit 1 +fi + +echo "Getting cert signing pod" +export CERT_POD=$(ssh $SERVER "kubectl get pod -n kube-system --selector=app=certsigner --output=jsonpath={.items..metadata.name}") + +if [ -z $CERT_POD ]; then + echo "Installing certsigner" + helm template certsigner ./certsigner | ssh $SERVER "sudo -t -E kubectl apply -f -" +fi + +while [ -z $CERT_POD ]; do + echo "Getting cert signing pod" + export CERT_POD=$(ssh $SERVER "kubectl get pod -n kube-system --selector=app=certsigner --output=jsonpath={.items..metadata.name}") + sleep 2 +done + +if [ $? -ne 0 ]; then +echo "Failed to install certsigner." +exit 1 +fi + +echo "Signing cert with pod $CERT_POD" +ssh $SERVER "kubectl -n kube-system cp $SERVER_USER_DIR/$USER.csr $CERT_POD:/certs/$USER.csr" +ssh $SERVER "kubectl -n kube-system exec $CERT_POD -- openssl x509 -in /certs/$USER.csr -req -CA /keys/client-ca.crt -CAkey /keys/client-ca.key -set_serial $(python -c 'import random; print(random.randint(1000000000, 9999999999))') -out /certs/$USER.crt -days 5000" +ssh $SERVER "kubectl -n kube-system cp $CERT_POD:/certs/$USER.crt ~/.kube/users/$USER/$USER.crt" +echo "retrieving signed cert" +scp $SERVER:$SERVER_USER_DIR/$USER.crt $CERT_DIR/$USER.crt + +echo "retrieving server ca" +wget --no-check-certificate https://$SERVER:6443/cacerts -O $CA_CERT_DIR/server-ca.pem + +echo "creating $SERVER-$USER context" +kubectl config set-context $SERVER-$USER + +echo "setting $SERVER-$USER as current context" +kubectl config set current-context $SERVER-$USER + +echo "adding server to config with new context $SERVER-$USER" +kubectl config set-cluster $SERVER --server=https://$SERVER:6443 --certificate-authority=$CA_CERT_DIR/server-ca.pem +kubectl config set contexts.$(kubectl config current-context).cluster $SERVER + +echo "adding user to config file" +kubectl config set-credentials $SERVER_USER --client-certificate=$CERT_DIR/$USER.crt --client-key=$CERT_DIR/$USER.key + +echo "setting user context" +kubectl config set contexts.$(kubectl config current-context).user $SERVER_USER + +if [ $USER = "admin" ]; then +echo "Admin user created, skipping namespace" +echo "export KUBECONFIG=$KUBECONFIG" +exit 0 +fi + +echo "Templating namespace with helm and copying to server" +helm template $USER --set user=$USER ./helm/namespace | ssh $SERVER "cat - > $SERVER_USER_DIR/namespace.yaml" + +if [ $? -ne 0 ]; then + echo "Failed to template namespace. Is helm installed?" + exit 1 +fi + +echo "Creating namespace from template" +ssh $SERVER "kubectl apply -f $SERVER_USER_DIR/namespace.yaml" + +echo "Setting namespace context" +kubectl config set contexts.$(kubectl config current-context).namespace $USER + +if [ $? -ne 0 ]; then + echo "Failed to create namespace" + exit 1 +fi + +echo "export KUBECONFIG=$KUBECONFIG" diff --git a/scripts/removeuser.sh b/scripts/removeuser.sh new file mode 100755 index 0000000..f96eaf2 --- /dev/null +++ b/scripts/removeuser.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +# Use +# ./removeuserspace + +export SERVER=$1 +export USER=$2 + +export CERT_DIR=$HOME/.kube/$SERVER/users/$USER +export CA_CERT_DIR=$HOME/.kube/$SERVER + +export SERVER_USER_DIR="~/.kube/users/$USER" +export SERVER_NAME=$(echo "$SERVER" | sed 's/\./-/g') +export SERVER_USER="$USER-$SERVER_NAME" + +export KUBECONFIG="$HOME/.kube/$USER-config" + +echo "Checking if project namespace exists" +exists=$(ssh $SERVER "kubectl get namespace --output=jsonpath=\"{.items[?(@.metadata.name=='$USER')].metadata.name}\"") +if [ -z $exists ]; then + echo "Namespace not found, nothing to delete" + exit 1 +else + echo "Namespace exists, deleting" +fi + +echo "Deleting user namespace" +ssh $SERVER "kubectl delete -f $SERVER_USER_DIR/namespace.yaml" + +echo "Deleting remote cert dir" +ssh $SERVER "rm -rf $SERVER_USER_DIR" + +echo "Deleting local cert dir" +rm -rf $CERT_DIR + +echo "Removing from kubeconfig" +kubectl config delete-user $SERVER_USER diff --git a/scripts/setup.sh b/scripts/setup.sh new file mode 100755 index 0000000..b5f7f9f --- /dev/null +++ b/scripts/setup.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +# Use +# ./setup.sh + +export SERVER=$1 + +ssh -t $SERVER sudo kubectl -n kube-system create secret generic certsigner --from-file /var/lib/rancher/k3s/server/tls/client-ca.crt --from-file /var/lib/rancher/k3s/server/tls/client-ca.key +scp certsigner.yaml $SERVER:~/certsigner.yaml +ssh $SERVER kubectl apply -f certsigner.yaml +scp clusterrole.yaml $SERVER:~/clusterrole.yaml +ssh $SERVER kubectl apply -f clusterrole.yaml diff --git a/scripts/updateprojectspace.sh b/scripts/updateprojectspace.sh new file mode 100755 index 0000000..dbb045c --- /dev/null +++ b/scripts/updateprojectspace.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +# Use +# ./updateprojectspace + +export SERVER=$1 +export USER=$2 +export PROJECT=$3 + +export SERVER_PROJECT_DIR="~/.kube/projects/$PROJECT" + +export KUBECONFIG="$HOME/.kube/$USER-config" + +echo "Checking if project namespace exists" +exists=$(ssh $SERVER "kubectl get namespace --output=jsonpath=\"{.items[?(@.metadata.name=='$PROJECT')].metadata.name}\"") +if [ -z $exists ]; then + echo "Namespace not found, nothing to update" + exit 1 +else + echo "Namespace exists, updating" +fi + +echo "Templating namespace with helm and copying to server" +helm template $PROJECT ./helm/namespace --set user=$USER | ssh $SERVER "cat - > $SERVER_PROJECT_DIR/namespace.yaml" + +if [ $? -ne 0 ]; then + echo "Failed to template namespace. Is helm installed?" + exit 1 +fi + +echo "Updating namespace with template" +ssh $SERVER "kubectl apply -f $SERVER_PROJECT_DIR/namespace.yaml" + +if [ $? -ne 0 ]; then + echo "Failed to update namespace" + exit 1 +fi + +echo "done"