From 53ed011e023d0b8afe98c900458bd7e4bba51505 Mon Sep 17 00:00:00 2001 From: Terry Cain Date: Fri, 25 Mar 2022 23:41:35 +0000 Subject: [PATCH] Cleanup --- .dockerignore | 3 + .github/workflows/build.yml | 64 ++++++++++++ .github/workflows/release.yml | 46 +++++++++ .golangci.yml | 178 +++++++++++++++++++++++++++++++++ Dockerfile | 16 +-- go.mod | 2 +- go.sum | 2 - kustomize/deployment.yaml | 32 ++++++ kustomize/kustomization.yaml | 5 + kustomize/role-binding.yaml | 13 +++ kustomize/role.yaml | 20 ++++ kustomize/service-account.yaml | 7 ++ main.go | 36 +++---- 13 files changed, 393 insertions(+), 31 deletions(-) create mode 100644 .dockerignore create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/release.yml create mode 100644 .golangci.yml create mode 100644 kustomize/deployment.yaml create mode 100644 kustomize/kustomization.yaml create mode 100644 kustomize/role-binding.yaml create mode 100644 kustomize/role.yaml create mode 100644 kustomize/service-account.yaml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..7a1e1af --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +.git +Dockerfile +README.md \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..141c616 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,64 @@ +name: "Build and Release" + +on: + push: + branches: + - master + pull_request: + branches: + - master + +jobs: + lint: + name: lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: golangci-lint + uses: golangci/golangci-lint-action@v2 + with: + version: latest + + build: + needs: lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Cache Docker layers + uses: actions/cache@v2 + with: + path: /tmp/.buildx-cache + key: ${{ runner.os }}-buildx + restore-keys: | + ${{ runner.os }}-buildx + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + + - name: Set up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@v1 + + - name: Build and push + uses: docker/build-push-action@v2 + with: + context: . + platforms: linux/amd64,linux/arm64 + push: false + tags: test + + kube: + name: kustomize-validation + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Validate Helm chart + uses: stefanprodan/kube-tools@v1 + with: + kubectl: 1.19.11 + helm: 2.17.0 + helmv3: 3.6.0 + command: | + kustomize build ./kustomize | kubeval --strict --kubernetes-version 1.23.5 --schema-location https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master + # Looted from https://github.com/stefanprodan/podinfo/blob/master/.github/workflows/test.yml + # kustomize build ./kustomize | conftest test -p .github/polic... diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..97dddb6 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,46 @@ +name: "Build and Release" + +on: + push: + tags: + - "*.*.*" + +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Cache Docker layers + uses: actions/cache@v2 + with: + path: /tmp/.buildx-cache + key: ${{ runner.os }}-buildx + restore-keys: | + ${{ runner.os }}-buildx + + - name: Get the version + id: get_version + run: echo ::set-output name=version::${GITHUB_REF/refs\/tags\//} + + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + + - name: Set up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@v1 + + - name: Log in to the Container registry + uses: docker/login-action@v1 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push + uses: docker/build-push-action@v2 + with: + context: . + platforms: linux/amd64,linux/arm64 + push: true + tags: ghcr.io/binkhq/kube-crb-manager:${{ steps.get_version.outputs.version }} \ No newline at end of file diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..ec87ba1 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,178 @@ +run: + timeout: 2m + # skip-dirs: + # - testdir + + # skip-files: + # - test.go + +output: + # colored-line-number|line-number|json|tab|checkstyle|code-climate|junit-xml|github-actions + format: colored-line-number + sort-results: true + + +linters-settings: + + cyclop: + # the maximal code complexity to report + max-complexity: 30 + # the maximal average package complexity. If it's higher than 0.0 (float) the check is enabled (default 0.0) + package-average: 0.0 + # should ignore tests (default false) + skip-tests: false + + dogsled: + # checks assignments with too many blank identifiers; default is 2 + max-blank-identifiers: 2 + + errorlint: + errorf: true + asserts: true + comparison: true + + gocognit: + # minimal code complexity to report, 30 by default (but we recommend 10-20) + min-complexity: 20 + + goconst: + # minimal length of string constant, 3 by default + min-len: 3 + # minimum occurrences of constant string count to trigger issue, 3 by default + min-occurrences: 3 + # ignore test files, false by default + ignore-tests: true + # look for existing constants matching the values, true by default + match-constant: true + # search also for duplicated numbers, false by default + numbers: false + # minimum value, only works with goconst.numbers, 3 by default + min: 3 + # maximum value, only works with goconst.numbers, 3 by default + max: 3 + # ignore when constant is not used as function argument, true by default + ignore-calls: true + + gocyclo: + # minimal code complexity to report, 30 by default (but we recommend 10-20) + min-complexity: 20 + + godot: + # comments to be checked: `declarations`, `toplevel`, or `all` + scope: declarations + # check that each sentence starts with a capital letter + capital: true + + godox: + # report any comments starting with keywords, this is useful for TODO or FIXME comments that + # might be left in the code accidentally and should be resolved before merging + keywords: # default keywords are TODO, BUG, and FIXME, these can be overwritten by this setting + - NOTE + #- TODO + - FIXME + - OPTIMIZE + - HACK + + gofmt: + # simplify code: gofmt with `-s` option, true by default + simplify: true + + gofumpt: + # Select the Go version to target. The default is `1.15`. + lang-version: "1.16" + + golint: + # minimal confidence for issues, default is 0.8 + min-confidence: 0.8 + + gosec: + # To select a subset of rules to run. + # Available rules: https://github.com/securego/gosec#available-rules + # includes: + # - G401 + # - G306 + # - G101 + # # To specify a set of rules to explicitly exclude. + # # Available rules: https://github.com/securego/gosec#available-rules + # excludes: + # - G204 + # To specify the configuration of rules. + # The configuration of rules is not fully documented by gosec: + # https://github.com/securego/gosec#configuration + # https://github.com/securego/gosec/blob/569328eade2ccbad4ce2d0f21ee158ab5356a5cf/rules/rulelist.go#L60-L102 + config: + G306: "0600" + G101: + pattern: "(?i)example" + ignore_entropy: false + entropy_threshold: "80.0" + per_char_threshold: "3.0" + truncate: "32" + + maligned: + # print struct with more effective memory layout or not, false by default + suggest-new: true + + misspell: + # Correct spellings using locale preferences for US or UK. + # Default is to use a neutral variety of English. + # Setting locale to US will correct the British spelling of 'colour' to 'color'. + locale: UK + ignore-words: + - someword + + # prealloc: + # # XXX: we don't recommend using this linter before doing performance profiling. + # # For most programs usage of prealloc will be a premature optimization. + # + # # Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them. + # # True by default. + # simple: true + # range-loops: true # Report preallocation suggestions on range loops, true by default + # for-loops: false # Report preallocation suggestions on for loops, false by default + + unused: + # Select the Go version to target. The default is '1.13'. + go: "1.16" + + # whitespace: + # multi-if: false # Enforces newlines (or comments) after every multi-line if statement + # multi-func: false # Enforces newlines (or comments) after every multi-line function signature + + govet: + # report about shadowed variables + check-shadowing: true + +linters: + enable: + - megacheck + - errcheck + - gosimple + - govet + - ineffassign + - staticcheck + - typecheck + - unused + - dogsled + - cyclop + - durationcheck + - errname + - goconst + - gocritic + - godot + - godox + - gofumpt + - gosec + - ifshort + - misspell + - predeclared + - revive + - unconvert + + disable: + - prealloc + - scopelint + presets: + - bugs + - unused + fast: false diff --git a/Dockerfile b/Dockerfile index c18e6ad..8eee016 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,15 +1,19 @@ -FROM golang:alpine AS build +FROM --platform=$BUILDPLATFORM golang:1.18-alpine3.15 AS build -RUN apk update && apk add --no-cache git ca-certificates && update-ca-certificates +RUN apk update && apk add --no-cache git ca-certificates && \ + update-ca-certificates -WORKDIR /go/src/git.bink.com/tools/blobfileexporter +WORKDIR /go/src/github.com/binkhq/kube-crb-manager COPY . . RUN go mod download RUN go mod verify -RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -o /a . + +ARG TARGETOS +ARG TARGETARCH +RUN GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=0 go build -ldflags="-w -s" -o /kube-crb-manager . FROM scratch COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ -COPY --from=build /a /a -ENTRYPOINT ["/a"] +COPY --from=build /kube-crb-manager /kube-crb-manager +ENTRYPOINT ["/kube-crb-manager"] diff --git a/go.mod b/go.mod index 9e0ce6f..d77f023 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module git.bink.com/tools/kube-crb-manager +module github.com/binkhq/kube-crb-manager go 1.14 diff --git a/go.sum b/go.sum index 61691bd..f452066 100644 --- a/go.sum +++ b/go.sum @@ -149,7 +149,6 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1 github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -448,7 +447,6 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/kustomize/deployment.yaml b/kustomize/deployment.yaml new file mode 100644 index 0000000..ae6cc45 --- /dev/null +++ b/kustomize/deployment.yaml @@ -0,0 +1,32 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: kube-crb-manager + namespace: kube-system + labels: + app: kube-crb-manager +spec: + replicas: 1 + strategy: + type: Recreate + selector: + matchLabels: + app: kube-crb-manager + template: + metadata: + labels: + app: kube-crb-manager + spec: + serviceAccountName: kube-crb-manager + containers: + - name: kube-crb-manager + image: ghcr.io/binkhq/kube-crb-manager:0.1.0 + env: + - name: AZURE_CLIENT_ID + value: REPLACE_ME + - name: AZURE_CLIENT_SECRET + value: REPLACE_ME + - name: AZURE_AD_GROUP_ID + value: REPLACE_ME + diff --git a/kustomize/kustomization.yaml b/kustomize/kustomization.yaml new file mode 100644 index 0000000..e2babb1 --- /dev/null +++ b/kustomize/kustomization.yaml @@ -0,0 +1,5 @@ +resources: + - deployment.yaml + - role.yaml + - role-binding.yaml + - service-account.yaml diff --git a/kustomize/role-binding.yaml b/kustomize/role-binding.yaml new file mode 100644 index 0000000..af4e57e --- /dev/null +++ b/kustomize/role-binding.yaml @@ -0,0 +1,13 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: kube-crb-manager + namespace: kube-system +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: kube-crb-manager +subjects: +- kind: ServiceAccount + name: kube-crb-manager + namespace: kube-system diff --git a/kustomize/role.yaml b/kustomize/role.yaml new file mode 100644 index 0000000..a8c0742 --- /dev/null +++ b/kustomize/role.yaml @@ -0,0 +1,20 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: kube-crb-manager + namespace: kube-system +rules: +- apiGroups: ["rbac.authorization.k8s.io"] + resources: + - clusterrolebindings + verbs: ["get", "list", "create", "delete"] +#- apiGroups: +# - '*' +# resources: +# - '*' +# verbs: +# - '*' +#- nonResourceURLs: +# - '*' +# verbs: +# - '*' diff --git a/kustomize/service-account.yaml b/kustomize/service-account.yaml new file mode 100644 index 0000000..671de6c --- /dev/null +++ b/kustomize/service-account.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: kube-crb-manager + namespace: kube-system + annotations: + kubernetes.io/service-account.name: kube-crb-manager diff --git a/main.go b/main.go index 6d2527f..2045c84 100644 --- a/main.go +++ b/main.go @@ -18,9 +18,7 @@ import ( "k8s.io/client-go/rest" ) -const CHECK_INTERVAL = 5 * time.Minute - -var aadPrefix = true +const CheckInterval = 5 * time.Minute func main() { zerolog.SetGlobalLevel(zerolog.InfoLevel) @@ -38,10 +36,7 @@ func main() { if len(groupID) == 0 { log.Fatal().Msgf("Environment variable AZURE_AD_GROUP_ID missing") } - prefix := os.Getenv("AAD_PREFIX") - if len(prefix) == 0 { - aadPrefix = false - } + _, aadPrefix := os.LookupEnv("AAD_PREFIX") for { // Get AAD users @@ -51,7 +46,7 @@ func main() { groupID) if err != nil { log.Error().Err(err).Msg("Failed to get list of users from Azure AD") - <-time.After(CHECK_INTERVAL) + <-time.After(CheckInterval) continue } @@ -59,7 +54,7 @@ func main() { kubeUsers, err := GetCRBsFromKube() if err != nil { log.Error().Err(err).Msg("Failed to get list of clusterroles from Kubernetes") - <-time.After(CHECK_INTERVAL) + <-time.After(CheckInterval) continue } @@ -67,19 +62,19 @@ func main() { err = DeleteCRBsFromKube(aadUsers, kubeUsers) if err != nil { log.Error().Err(err).Msg("Failed to delete CRBs from Kubernetes") - <-time.After(CHECK_INTERVAL) + <-time.After(CheckInterval) continue } // Add users - err = AddCRBsToKube(aadUsers, kubeUsers) + err = AddCRBsToKube(aadUsers, kubeUsers, aadPrefix) if err != nil { log.Error().Err(err).Msg("Failed to add CRBs from Kubernetes") - <-time.After(CHECK_INTERVAL) + <-time.After(CheckInterval) continue } - <-time.After(CHECK_INTERVAL) + <-time.After(CheckInterval) } } @@ -180,17 +175,14 @@ func DeleteCRBsFromKube(aadUsers, kubeUsers map[string]string) error { return nil } -func prefix(email string) string { - var response string - if aadPrefix { - response = "aad:" + email - } else { - response = email +func aadPrefix(email string, withAadPrefix bool) string { + if withAadPrefix { + return "aad:" + email } - return response + return email } -func AddCRBsToKube(aadUsers, kubeUsers map[string]string) error { +func AddCRBsToKube(aadUsers, kubeUsers map[string]string, withAadPrefix bool) error { config, err := rest.InClusterConfig() if err != nil { return err @@ -224,7 +216,7 @@ func AddCRBsToKube(aadUsers, kubeUsers map[string]string) error { { APIGroup: "rbac.authorization.k8s.io", Kind: "User", - Name: prefix(email), + Name: aadPrefix(email, withAadPrefix), }, }, RoleRef: rbacv1.RoleRef{