diff --git a/Dockerfile.dapper b/Dockerfile.dapper index 1882c87..1c9d0af 100644 --- a/Dockerfile.dapper +++ b/Dockerfile.dapper @@ -17,6 +17,7 @@ RUN if [ "${ARCH}" == "amd64" ]; then \ curl -sL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s v1.15.0; \ fi +ENV GO111MODULE off ENV DAPPER_ENV REPO TAG DRONE_TAG ENV DAPPER_SOURCE /go/src/github.com/ibuildthecloud/klum/ ENV DAPPER_OUTPUT ./bin ./dist diff --git a/README.md b/README.md index a851b9e..1fda5db 100644 --- a/README.md +++ b/README.md @@ -27,18 +27,18 @@ metadata: name: darren ``` -## Download Kubeconfig +### Download Kubeconfig ```shell script kubectl get kubeconfig darren -o json | jq .spec > ~/.kube/config ``` The name of the kubeconfig resource will be the same as the user name -## Delete User +### Delete User ```shell script kubectl delete user darren ``` -## Assign Roles +### Assign Roles ```yaml kind: User apiVersion: klum.cattle.io/v1alpha1 @@ -56,6 +56,18 @@ spec: role: something-custom ``` +### Disable user +```yaml +kind: User +apiVersion: klum.cattle.io/v1alpha1 +metadata: + name: darren +spec: + enabled: false +``` + +When the user is reenabled a new kubeconfig with new token will be created. + ## Configuration The controller can be configured as follows. You will need to edit the deployment and change then environment variables: @@ -73,6 +85,7 @@ GLOBAL OPTIONS: `make` or just `go build` +![](https://media.giphy.com/media/3o7TKGMZHi73yzCumQ/giphy.gif) ## Running diff --git a/deploy.yaml b/deploy.yaml new file mode 100644 index 0000000..cdc966a --- /dev/null +++ b/deploy.yaml @@ -0,0 +1,51 @@ +--- + +apiVersion: v1 +kind: Namespace +metadata: + name: klum + +--- + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: klum + namespace: klum +spec: + replicas: 1 + selector: + matchLabels: + run: klum + template: + metadata: + labels: + run: klum + spec: + serviceAccountName: klum + containers: + - image: ibuildthecloud/klum:dev + name: klum + +--- + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: klum + namespace: klum + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: klum-cluster-admin +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cluster-admin +subjects: +- kind: ServiceAccount + name: klum + namespace: klum diff --git a/main.go b/main.go index a0a8689..433d95f 100644 --- a/main.go +++ b/main.go @@ -1,5 +1,4 @@ //go:generate go run pkg/codegen/cleanup/main.go -//go:generate /bin/rm -rf pkg/generated //go:generate go run pkg/codegen/main.go package main @@ -7,6 +6,8 @@ package main import ( "context" "fmt" + "os" + "github.com/ibuildthecloud/klum/pkg/controllers/user" "github.com/ibuildthecloud/klum/pkg/crd" "github.com/ibuildthecloud/klum/pkg/generated/controllers/klum.cattle.io" @@ -18,7 +19,6 @@ import ( "github.com/rancher/wrangler/pkg/start" "github.com/sirupsen/logrus" "github.com/urfave/cli" - "os" ) var ( @@ -64,7 +64,7 @@ func main() { Name: "ca", Usage: "The value of the CA data to put in the Kubeconfig", EnvVar: "CA", - Destination: &cfg.Server, + Destination: &cfg.CA, }, cli.StringFlag{ Name: "default-cluster-role", @@ -94,7 +94,7 @@ func run(c *cli.Context) error { return err } - core, err := core.NewFactoryFromConfigWithNamespace(restConfig, cfg.Namespace) + core, err := core.NewFactoryFromConfig(restConfig) if err != nil { return err } @@ -104,7 +104,7 @@ func run(c *cli.Context) error { return err } - rbac, err := rbac.NewFactoryFromConfigWithNamespace(restConfig, cfg.Namespace) + rbac, err := rbac.NewFactoryFromConfig(restConfig) if err != nil { return err } @@ -119,6 +119,7 @@ func run(c *cli.Context) error { apply, core.Core().V1().ServiceAccount(), rbac.Rbac().V1().ClusterRoleBinding(), + rbac.Rbac().V1().RoleBinding(), core.Core().V1().Secret(), klum.Klum().V1alpha1().Kubeconfig(), klum.Klum().V1alpha1().User()) diff --git a/package/Dockerfile b/package/Dockerfile index 7223943..8ef57a9 100644 --- a/package/Dockerfile +++ b/package/Dockerfile @@ -1,3 +1,3 @@ -FROM alpine -COPY bin/klum /usr/bin/ -CMD ["klum"] +FROM scratch +COPY bin/klum /klum +CMD ["/klum"] diff --git a/pkg/apis/klum.cattle.io/v1alpha1/types.go b/pkg/apis/klum.cattle.io/v1alpha1/types.go index 1a623a0..246e234 100644 --- a/pkg/apis/klum.cattle.io/v1alpha1/types.go +++ b/pkg/apis/klum.cattle.io/v1alpha1/types.go @@ -17,14 +17,14 @@ var ( type User struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` - Spec UserSpec `json:"spec,omitempty"` - Status UserStatus `json:"status,omitempty"` + Spec UserSpec `json:"spec,omitempty"` + Status UserStatus `json:"status,omitempty"` } type UserSpec struct { - Enabled *bool `json:"enabled,omitempty"` - ClusterRoles []string `json:"clusterRoles,omitempty"` - Roles []NamespaceRole `json:"roles,omitempty"` + Enabled *bool `json:"enabled,omitempty"` + ClusterRoles []string `json:"clusterRoles,omitempty"` + Roles []NamespaceRole `json:"roles,omitempty"` } type UserStatus struct { @@ -32,9 +32,9 @@ type UserStatus struct { } type NamespaceRole struct { - Namespace string `json:"namespace,omitempty"` - ClusterRole string `json:"clusterRole,omitempty"` - Role string `json:"role,omitempty"` + Namespace string `json:"namespace,omitempty"` + ClusterRole string `json:"clusterRole,omitempty"` + Role string `json:"role,omitempty"` } // +genclient diff --git a/pkg/codegen/cleanup/main.go b/pkg/codegen/cleanup/main.go index a97b63a..3c22fbd 100644 --- a/pkg/codegen/cleanup/main.go +++ b/pkg/codegen/cleanup/main.go @@ -1,9 +1,10 @@ package main import ( + "os" + "github.com/rancher/wrangler/pkg/cleanup" "github.com/sirupsen/logrus" - "os" ) func main() { diff --git a/pkg/codegen/main.go b/pkg/codegen/main.go index 528545e..ce24539 100644 --- a/pkg/codegen/main.go +++ b/pkg/codegen/main.go @@ -1,10 +1,11 @@ package main import ( - "github.com/ibuildthecloud/klum/pkg/apis/klum.cattle.io/v1alpha1" - "github.com/rancher/wrangler/pkg/controller-gen" - "github.com/rancher/wrangler/pkg/controller-gen/args" "os" + + "github.com/ibuildthecloud/klum/pkg/apis/klum.cattle.io/v1alpha1" + controllergen "github.com/rancher/wrangler/pkg/controller-gen" + "github.com/rancher/wrangler/pkg/controller-gen/args" ) func main() { diff --git a/pkg/controllers/user/controller.go b/pkg/controllers/user/controller.go index 323aebe..393696a 100644 --- a/pkg/controllers/user/controller.go +++ b/pkg/controllers/user/controller.go @@ -6,6 +6,7 @@ import ( "encoding/base64" "encoding/hex" "fmt" + klum "github.com/ibuildthecloud/klum/pkg/apis/klum.cattle.io/v1alpha1" "github.com/ibuildthecloud/klum/pkg/generated/controllers/klum.cattle.io/v1alpha1" v1controller "github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1" @@ -34,6 +35,7 @@ func Register(ctx context.Context, apply apply.Apply, serviceAccount v1controller.ServiceAccountController, crb rbaccontroller.ClusterRoleBindingController, + rb rbaccontroller.RoleBindingController, secrets v1controller.SecretController, kconfig v1alpha1.KubeconfigController, user v1alpha1.UserController) { @@ -47,7 +49,7 @@ func Register(ctx context.Context, v1alpha1.RegisterUserGeneratingHandler(ctx, user, apply.WithCacheTypes(serviceAccount, - crb), + crb, rb), "", "klum-user", h.OnUserChange, @@ -136,37 +138,48 @@ func (h *handler) getRoles(user *klum.User) []runtime.Object { continue } - rb := &rbacv1.RoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: name(user.Name, role.Namespace, role.ClusterRole, role.Role), - Namespace: role.Namespace, - }, - Subjects: subjects, - } - if role.Role != "" { - rb.RoleRef = rbacv1.RoleRef{ - APIGroup: "rbac.authorization.k8s.io", - Kind: "Role", - Name: role.Role, - } - } else { - rb.RoleRef = rbacv1.RoleRef{ - APIGroup: "rbac.authorization.k8s.io", - Kind: "ClusterRole", - Name: role.ClusterRole, + rb := &rbacv1.RoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: name(user.Name, role.Namespace, "", role.Role), + Namespace: role.Namespace, + }, + Subjects: subjects, + RoleRef: rbacv1.RoleRef{ + APIGroup: "rbac.authorization.k8s.io", + Kind: "Role", + Name: role.Role, + }, } + objs = append(objs, rb) } - objs = append(objs, rb) + if role.ClusterRole != "" { + rb := &rbacv1.RoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: name(user.Name, role.Namespace, role.ClusterRole, ""), + Namespace: role.Namespace, + }, + Subjects: subjects, + RoleRef: rbacv1.RoleRef{ + APIGroup: "rbac.authorization.k8s.io", + Kind: "ClusterRole", + Name: role.ClusterRole, + }, + } + objs = append(objs, rb) + } } return objs } func name(user, namespace, clusterRole, role string) string { - // this is so we don't get conflics + // this is so we don't get conflicts suffix := md5.Sum([]byte(fmt.Sprintf("%s/%s/%s/%s", user, namespace, clusterRole, role))) + if role == "" { + role = clusterRole + } return name2.SafeConcatName("klum", user, role, hex.EncodeToString(suffix[:])[:8]) } diff --git a/pkg/crd/create.go b/pkg/crd/create.go index a6c442c..c0ee34d 100644 --- a/pkg/crd/create.go +++ b/pkg/crd/create.go @@ -2,6 +2,7 @@ package crd import ( "context" + "github.com/ibuildthecloud/klum/pkg/apis/klum.cattle.io/v1alpha1" "github.com/rancher/norman/v2/pkg/openapi" "github.com/rancher/wrangler/pkg/crd" diff --git a/scripts/validate b/scripts/validate index 6f7fc88..7f98128 100755 --- a/scripts/validate +++ b/scripts/validate @@ -19,6 +19,3 @@ golangci-lint run echo Running: go fmt test -z "$(go fmt ${PACKAGES} | tee /dev/stderr)" - -echo Running: go mod verify -go mod verify \ No newline at end of file