diff --git a/Makefile b/Makefile index c69bb9a..5a407a3 100644 --- a/Makefile +++ b/Makefile @@ -5,24 +5,6 @@ # - use environment variables to overwrite this value (e.g export VERSION=0.0.2) VERSION ?= 0.0.1 -# CHANNELS define the bundle channels used in the bundle. -# Add a new line here if you would like to change its default config. (E.g CHANNELS = "candidate,fast,stable") -# To re-generate a bundle for other specific channels without changing the standard setup, you can: -# - use the CHANNELS as arg of the bundle target (e.g make bundle CHANNELS=candidate,fast,stable) -# - use environment variables to overwrite this value (e.g export CHANNELS="candidate,fast,stable") -ifneq ($(origin CHANNELS), undefined) -BUNDLE_CHANNELS := --channels=$(CHANNELS) -endif - -# DEFAULT_CHANNEL defines the default channel used in the bundle. -# Add a new line here if you would like to change its default config. (E.g DEFAULT_CHANNEL = "stable") -# To re-generate a bundle for any other default channel without changing the default setup, you can: -# - use the DEFAULT_CHANNEL as arg of the bundle target (e.g make bundle DEFAULT_CHANNEL=stable) -# - use environment variables to overwrite this value (e.g export DEFAULT_CHANNEL="stable") -ifneq ($(origin DEFAULT_CHANNEL), undefined) -BUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL) -endif -BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL) # IMAGE_TAG_BASE defines the docker.io namespace and part of the image name for remote images. # This variable is used to construct full image tags for bundle and catalog images. @@ -31,29 +13,9 @@ BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL) # kkb0318.github.io/irsa-manager-bundle:$VERSION and kkb0318.github.io/irsa-manager-catalog:$VERSION. IMAGE_TAG_BASE ?= kkb0318.github.io/irsa-manager -# BUNDLE_IMG defines the image:tag used for the bundle. -# You can use it as an arg. (E.g make bundle-build BUNDLE_IMG=/:) -BUNDLE_IMG ?= $(IMAGE_TAG_BASE)-bundle:v$(VERSION) - -# BUNDLE_GEN_FLAGS are the flags passed to the operator-sdk generate bundle command -BUNDLE_GEN_FLAGS ?= -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS) - -# USE_IMAGE_DIGESTS defines if images are resolved via tags or digests -# You can enable this value if you would like to use SHA Based Digests -# To enable set flag to true -USE_IMAGE_DIGESTS ?= false -ifeq ($(USE_IMAGE_DIGESTS), true) - BUNDLE_GEN_FLAGS += --use-image-digests -endif - -# Set the Operator SDK version to use. By default, what is installed on the system is used. -# This is useful for CI or a project to utilize a specific version of the operator-sdk toolkit. -OPERATOR_SDK_VERSION ?= v1.34.1 # Image URL to use all building/pushing image targets IMG ?= controller:latest -# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary. -ENVTEST_K8S_VERSION = 1.28.3 # Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set) ifeq (,$(shell go env GOBIN)) @@ -73,28 +35,42 @@ CONTAINER_TOOL ?= docker SHELL = /usr/bin/env bash -o pipefail .SHELLFLAGS = -ec +## Location to install dependencies to +LOCALBIN ?= $(shell pwd)/bin +$(LOCALBIN): + mkdir -p $(LOCALBIN) + +## Tool Binaries +KUBECTL ?= kubectl +KUSTOMIZE ?= $(LOCALBIN)/kustomize +CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen +HELM_DOCS ?= $(LOCALBIN)/helm-docs +ENVTEST ?= $(LOCALBIN)/setup-envtest +HELMIFY ?= $(LOCALBIN)/helmify +CRD_REF_DOCS ?= $(LOCALBIN)/crd-ref-docs + +## Tool Versions +KUSTOMIZE_VERSION ?= v5.2.1 +CONTROLLER_TOOLS_VERSION ?= v0.14.0 +# Set the Operator SDK version to use. By default, what is installed on the system is used. +# This is useful for CI or a project to utilize a specific version of the operator-sdk toolkit. +OPERATOR_SDK_VERSION ?= v1.34.1 +# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary. +ENVTEST_K8S_VERSION = 1.28.3 +# CRD_REF_DOCS_VERSION +CRD_REF_DOCS_VERSION = v0.0.12 + + .PHONY: all all: build -##@ General - -# The help target prints out all targets with their descriptions organized -# beneath their categories. The categories are represented by '##@' and the -# target descriptions by '##'. The awk command is responsible for reading the -# entire set of makefiles included in this invocation, looking for lines of the -# file as xyz: ## something, and then pretty-format the target and help. Then, -# if there's a line with ##@ something, that gets pretty-printed as a category. -# More info on the usage of ANSI control characters for terminal formatting: -# https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters -# More info on the awk command: -# http://linuxcommand.org/lc3_adv_awk.php - -.PHONY: help -help: ## Display this help. - @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) ##@ Development +helm: manifests kustomize helmify + $(KUSTOMIZE) build config/release | $(HELMIFY) -crd-dir charts/irsa-manager + + .PHONY: manifests manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects. $(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases @@ -136,6 +112,23 @@ lint: golangci-lint ## Run golangci-lint linter & yamllint lint-fix: golangci-lint ## Run golangci-lint linter and perform fixes $(GOLANGCI_LINT) run --fix + +##@ Gen Docs + +.PHONY: generate-docs +generate-docs: gen-helm-docs gen-crd-docs + +.PHONY: gen-helm-docs +gen-helm-docs: $(HELM_DOCS) ## create helm docs. + $(HELM_DOCS) --chart-search-root=./charts/irsa-manager + +.PHONY: gen-crd-docs +gen-crd-docs: crd-ref-docs + # $(CRD_REF_DOCS) --config=doc/config.yaml --source-path=api/ --renderer=markdown --templates-dir=doc/templates --output-path=doc/api.md + $(CRD_REF_DOCS) --source-path=api/ --renderer=markdown --config=docs/config.yaml --output-path=docs/api.md + + + ##@ Build .PHONY: build @@ -146,34 +139,6 @@ build: manifests generate fmt vet ## Build manager binary. run: manifests generate fmt vet ## Run a controller from your host. go run ./cmd/main.go -# If you wish to build the manager image targeting other platforms you can use the --platform flag. -# (i.e. docker build --platform linux/arm64). However, you must enable docker buildKit for it. -# More info: https://docs.docker.com/develop/develop-images/build_enhancements/ -.PHONY: docker-build -docker-build: ## Build docker image with the manager. - $(CONTAINER_TOOL) build -t ${IMG} . - -.PHONY: docker-push -docker-push: ## Push docker image with the manager. - $(CONTAINER_TOOL) push ${IMG} - -# PLATFORMS defines the target platforms for the manager image be built to provide support to multiple -# architectures. (i.e. make docker-buildx IMG=myregistry/mypoperator:0.0.1). To use this option you need to: -# - be able to use docker buildx. More info: https://docs.docker.com/build/buildx/ -# - have enabled BuildKit. More info: https://docs.docker.com/develop/develop-images/build_enhancements/ -# - be able to push the image to your registry (i.e. if you do not set a valid value via IMG=> then the export will fail) -# To adequately provide solutions that are compatible with multiple platforms, you should consider using this option. -PLATFORMS ?= linux/arm64,linux/amd64,linux/s390x,linux/ppc64le -.PHONY: docker-buildx -docker-buildx: ## Build and push docker image for the manager for cross-platform support - # copy existing Dockerfile and insert --platform=${BUILDPLATFORM} into Dockerfile.cross, and preserve the original Dockerfile - sed -e '1 s/\(^FROM\)/FROM --platform=\$$\{BUILDPLATFORM\}/; t' -e ' 1,// s//FROM --platform=\$$\{BUILDPLATFORM\}/' Dockerfile > Dockerfile.cross - - $(CONTAINER_TOOL) buildx create --name project-v3-builder - $(CONTAINER_TOOL) buildx use project-v3-builder - - $(CONTAINER_TOOL) buildx build --push --platform=$(PLATFORMS) --tag ${IMG} -f Dockerfile.cross . - - $(CONTAINER_TOOL) buildx rm project-v3-builder - rm Dockerfile.cross - ##@ Deployment ifndef ignore-not-found @@ -199,21 +164,6 @@ undeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/confi ##@ Build Dependencies -## Location to install dependencies to -LOCALBIN ?= $(shell pwd)/bin -$(LOCALBIN): - mkdir -p $(LOCALBIN) - -## Tool Binaries -KUBECTL ?= kubectl -KUSTOMIZE ?= $(LOCALBIN)/kustomize -CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen -ENVTEST ?= $(LOCALBIN)/setup-envtest - -## Tool Versions -KUSTOMIZE_VERSION ?= v5.2.1 -CONTROLLER_TOOLS_VERSION ?= v0.14.0 - .PHONY: kustomize kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary. If wrong version is installed, it will be removed before downloading. $(KUSTOMIZE): $(LOCALBIN) @@ -234,6 +184,21 @@ envtest: $(ENVTEST) ## Download envtest-setup locally if necessary. $(ENVTEST): $(LOCALBIN) test -s $(LOCALBIN)/setup-envtest || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest +.PHONY: helmify +helmify: $(HELMIFY) ## Download helmify locally if necessary. +$(HELMIFY): $(LOCALBIN) + test -s $(LOCALBIN)/helmify || GOBIN=$(LOCALBIN) go install github.com/arttor/helmify/cmd/helmify@latest + +.PHONY: helm-docs +helm-docs: $(HELM_DOCS) ## Download helm-docs locally if necessary. +$(HELM_DOCS): $(LOCALBIN) + test -s $(LOCALBIN)/helm-docs || GOBIN=$(LOCALBIN) go install github.com/norwoodj/helm-docs/cmd/helm-docs@latest + +.PHONY: crd-ref-docs +crd-ref-docs: $(CRD_REF_DOCS) ## Download crd-ref-docs locally if necessary. +$(CRD_REF_DOCS): $(LOCALBIN) + test -s $(LOCALBIN)/crd-ref-docs || GOBIN=$(LOCALBIN) go install github.com/elastic/crd-ref-docs@$(CRD_REF_DOCS_VERSION) + .PHONY: operator-sdk OPERATOR_SDK ?= $(LOCALBIN)/operator-sdk operator-sdk: ## Download operator-sdk locally if necessary. @@ -251,58 +216,3 @@ OPERATOR_SDK = $(shell which operator-sdk) endif endif -.PHONY: bundle -bundle: manifests kustomize operator-sdk ## Generate bundle manifests and metadata, then validate generated files. - $(OPERATOR_SDK) generate kustomize manifests -q - cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG) - $(KUSTOMIZE) build config/manifests | $(OPERATOR_SDK) generate bundle $(BUNDLE_GEN_FLAGS) - $(OPERATOR_SDK) bundle validate ./bundle - -.PHONY: bundle-build -bundle-build: ## Build the bundle image. - docker build -f bundle.Dockerfile -t $(BUNDLE_IMG) . - -.PHONY: bundle-push -bundle-push: ## Push the bundle image. - $(MAKE) docker-push IMG=$(BUNDLE_IMG) - -.PHONY: opm -OPM = $(LOCALBIN)/opm -opm: ## Download opm locally if necessary. -ifeq (,$(wildcard $(OPM))) -ifeq (,$(shell which opm 2>/dev/null)) - @{ \ - set -e ;\ - mkdir -p $(dir $(OPM)) ;\ - OS=$(shell go env GOOS) && ARCH=$(shell go env GOARCH) && \ - curl -sSLo $(OPM) https://github.com/operator-framework/operator-registry/releases/download/v1.23.0/$${OS}-$${ARCH}-opm ;\ - chmod +x $(OPM) ;\ - } -else -OPM = $(shell which opm) -endif -endif - -# A comma-separated list of bundle images (e.g. make catalog-build BUNDLE_IMGS=example.com/operator-bundle:v0.1.0,example.com/operator-bundle:v0.2.0). -# These images MUST exist in a registry and be pull-able. -BUNDLE_IMGS ?= $(BUNDLE_IMG) - -# The image tag given to the resulting catalog image (e.g. make catalog-build CATALOG_IMG=example.com/operator-catalog:v0.2.0). -CATALOG_IMG ?= $(IMAGE_TAG_BASE)-catalog:v$(VERSION) - -# Set CATALOG_BASE_IMG to an existing catalog image tag to add $BUNDLE_IMGS to that image. -ifneq ($(origin CATALOG_BASE_IMG), undefined) -FROM_INDEX_OPT := --from-index $(CATALOG_BASE_IMG) -endif - -# Build a catalog image by adding bundle images to an empty catalog using the operator package manager tool, 'opm'. -# This recipe invokes 'opm' in 'semver' bundle add mode. For more information on add modes, see: -# https://github.com/operator-framework/community-operators/blob/7f1438c/docs/packaging-operator.md#updating-your-existing-operator -.PHONY: catalog-build -catalog-build: opm ## Build a catalog image. - $(OPM) index add --container-tool docker --mode semver --tag $(CATALOG_IMG) --bundles $(BUNDLE_IMGS) $(FROM_INDEX_OPT) - -# Push the catalog image. -.PHONY: catalog-push -catalog-push: ## Push a catalog image. - $(MAKE) docker-push IMG=$(CATALOG_IMG) diff --git a/charts/irsa-manager/.helmignore b/charts/irsa-manager/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/charts/irsa-manager/.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/charts/irsa-manager/Chart.yaml b/charts/irsa-manager/Chart.yaml new file mode 100644 index 0000000..9703a8b --- /dev/null +++ b/charts/irsa-manager/Chart.yaml @@ -0,0 +1,21 @@ +apiVersion: v2 +name: irsa-manager +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.1.0 +# 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. +# It is recommended to use it with quotes. +appVersion: "0.1.0" diff --git a/charts/irsa-manager/README.md b/charts/irsa-manager/README.md new file mode 100644 index 0000000..8c95f0c --- /dev/null +++ b/charts/irsa-manager/README.md @@ -0,0 +1,42 @@ +# irsa-manager + +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.1.0](https://img.shields.io/badge/AppVersion-0.1.0-informational?style=flat-square) + +A Helm chart for Kubernetes + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| controllerManager.kubeRbacProxy.args[0] | string | `"--secure-listen-address=0.0.0.0:8443"` | | +| controllerManager.kubeRbacProxy.args[1] | string | `"--upstream=http://127.0.0.1:8080/"` | | +| controllerManager.kubeRbacProxy.args[2] | string | `"--logtostderr=true"` | | +| controllerManager.kubeRbacProxy.args[3] | string | `"--v=0"` | | +| controllerManager.kubeRbacProxy.containerSecurityContext.allowPrivilegeEscalation | bool | `false` | | +| controllerManager.kubeRbacProxy.containerSecurityContext.capabilities.drop[0] | string | `"ALL"` | | +| controllerManager.kubeRbacProxy.image.repository | string | `"gcr.io/kubebuilder/kube-rbac-proxy"` | | +| controllerManager.kubeRbacProxy.image.tag | string | `"v0.15.0"` | | +| controllerManager.kubeRbacProxy.resources.limits.cpu | string | `"500m"` | | +| controllerManager.kubeRbacProxy.resources.limits.memory | string | `"128Mi"` | | +| controllerManager.kubeRbacProxy.resources.requests.cpu | string | `"5m"` | | +| controllerManager.kubeRbacProxy.resources.requests.memory | string | `"64Mi"` | | +| controllerManager.manager.args[0] | string | `"--health-probe-bind-address=:8081"` | | +| controllerManager.manager.args[1] | string | `"--metrics-bind-address=127.0.0.1:8080"` | | +| controllerManager.manager.args[2] | string | `"--leader-elect"` | | +| controllerManager.manager.containerSecurityContext.allowPrivilegeEscalation | bool | `false` | | +| controllerManager.manager.containerSecurityContext.capabilities.drop[0] | string | `"ALL"` | | +| controllerManager.manager.image.repository | string | `"controller"` | | +| controllerManager.manager.image.tag | string | `"latest"` | | +| controllerManager.manager.resources.limits.cpu | string | `"500m"` | | +| controllerManager.manager.resources.limits.memory | string | `"128Mi"` | | +| controllerManager.manager.resources.requests.cpu | string | `"10m"` | | +| controllerManager.manager.resources.requests.memory | string | `"64Mi"` | | +| controllerManager.replicas | int | `1` | | +| controllerManager.serviceAccount.annotations | object | `{}` | | +| kubernetesClusterDomain | string | `"cluster.local"` | | +| metricsService.ports[0].name | string | `"https"` | | +| metricsService.ports[0].port | int | `8443` | | +| metricsService.ports[0].protocol | string | `"TCP"` | | +| metricsService.ports[0].targetPort | string | `"https"` | | +| metricsService.type | string | `"ClusterIP"` | | + diff --git a/charts/irsa-manager/crds/irsasetup-crd.yaml b/charts/irsa-manager/crds/irsasetup-crd.yaml new file mode 100644 index 0000000..a0c69db --- /dev/null +++ b/charts/irsa-manager/crds/irsasetup-crd.yaml @@ -0,0 +1,98 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: irsasetups.irsa.kkb0318.github.io +spec: + group: irsa.kkb0318.github.io + names: + kind: IRSASetup + listKind: IRSASetupList + plural: irsasetups + singular: irsasetup + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: IRSASetup represents a configuration for setting up IAM Roles + for Service Accounts (IRSA) in a Kubernetes cluster. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: IRSASetupSpec defines the desired state of IRSASetup + properties: + auth: + description: Auth contains authentication configuration details. + properties: + secretRef: + description: SecretRef specifies the reference to the Kubernetes + secret containing authentication details. + properties: + name: + description: Name specifies the name of the secret. + type: string + namespace: + description: Namespace specifies the namespace of the secret. + type: string + required: + - name + type: object + required: + - secretRef + type: object + discovery: + description: |- + Discovery configures the IdP Discovery process, essential for setting up IRSA by locating + the OIDC provider information. + properties: + s3: + description: S3 specifies the AWS S3 bucket details where the + OIDC provider's discovery information is hosted. + properties: + bucketName: + description: BucketName is the name of the S3 bucket that + hosts the OIDC discovery information. + type: string + region: + description: Region denotes the AWS region where the S3 bucket + is located. + type: string + required: + - bucketName + - region + type: object + type: object + mode: + description: Mode specifies the mode of operation. Can be either "selfhosted" + or "eks". + type: string + required: + - discovery + - mode + type: object + status: + description: IRSASetupStatus defines the observed state of IRSASetup + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/charts/irsa-manager/templates/_helpers.tpl b/charts/irsa-manager/templates/_helpers.tpl new file mode 100644 index 0000000..f88d404 --- /dev/null +++ b/charts/irsa-manager/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "irsa-manager.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "irsa-manager.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "irsa-manager.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "irsa-manager.labels" -}} +helm.sh/chart: {{ include "irsa-manager.chart" . }} +{{ include "irsa-manager.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "irsa-manager.selectorLabels" -}} +app.kubernetes.io/name: {{ include "irsa-manager.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "irsa-manager.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "irsa-manager.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/charts/irsa-manager/templates/deployment.yaml b/charts/irsa-manager/templates/deployment.yaml new file mode 100644 index 0000000..ed8428b --- /dev/null +++ b/charts/irsa-manager/templates/deployment.yaml @@ -0,0 +1,69 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "irsa-manager.fullname" . }}-controller-manager + labels: + app.kubernetes.io/component: manager + app.kubernetes.io/created-by: irsa-manager + app.kubernetes.io/part-of: irsa-manager + control-plane: controller-manager + {{- include "irsa-manager.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.controllerManager.replicas }} + selector: + matchLabels: + control-plane: controller-manager + {{- include "irsa-manager.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + control-plane: controller-manager + {{- include "irsa-manager.selectorLabels" . | nindent 8 }} + annotations: + kubectl.kubernetes.io/default-container: manager + spec: + containers: + - args: {{- toYaml .Values.controllerManager.kubeRbacProxy.args | nindent 8 }} + env: + - name: KUBERNETES_CLUSTER_DOMAIN + value: {{ quote .Values.kubernetesClusterDomain }} + image: {{ .Values.controllerManager.kubeRbacProxy.image.repository }}:{{ .Values.controllerManager.kubeRbacProxy.image.tag + | default .Chart.AppVersion }} + name: kube-rbac-proxy + ports: + - containerPort: 8443 + name: https + protocol: TCP + resources: {{- toYaml .Values.controllerManager.kubeRbacProxy.resources | nindent + 10 }} + securityContext: {{- toYaml .Values.controllerManager.kubeRbacProxy.containerSecurityContext + | nindent 10 }} + - args: {{- toYaml .Values.controllerManager.manager.args | nindent 8 }} + command: + - /manager + env: + - name: KUBERNETES_CLUSTER_DOMAIN + value: {{ quote .Values.kubernetesClusterDomain }} + image: {{ .Values.controllerManager.manager.image.repository }}:{{ .Values.controllerManager.manager.image.tag + | default .Chart.AppVersion }} + livenessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 15 + periodSeconds: 20 + name: manager + readinessProbe: + httpGet: + path: /readyz + port: 8081 + initialDelaySeconds: 5 + periodSeconds: 10 + resources: {{- toYaml .Values.controllerManager.manager.resources | nindent 10 + }} + securityContext: {{- toYaml .Values.controllerManager.manager.containerSecurityContext + | nindent 10 }} + securityContext: + runAsNonRoot: true + serviceAccountName: {{ include "irsa-manager.fullname" . }}-controller-manager + terminationGracePeriodSeconds: 10 \ No newline at end of file diff --git a/charts/irsa-manager/templates/leader-election-rbac.yaml b/charts/irsa-manager/templates/leader-election-rbac.yaml new file mode 100644 index 0000000..c243734 --- /dev/null +++ b/charts/irsa-manager/templates/leader-election-rbac.yaml @@ -0,0 +1,59 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "irsa-manager.fullname" . }}-leader-election-role + labels: + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: irsa-manager + app.kubernetes.io/part-of: irsa-manager + {{- include "irsa-manager.labels" . | nindent 4 }} +rules: +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "irsa-manager.fullname" . }}-leader-election-rolebinding + labels: + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: irsa-manager + app.kubernetes.io/part-of: irsa-manager + {{- include "irsa-manager.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: '{{ include "irsa-manager.fullname" . }}-leader-election-role' +subjects: +- kind: ServiceAccount + name: '{{ include "irsa-manager.fullname" . }}-controller-manager' + namespace: '{{ .Release.Namespace }}' \ No newline at end of file diff --git a/charts/irsa-manager/templates/manager-rbac.yaml b/charts/irsa-manager/templates/manager-rbac.yaml new file mode 100644 index 0000000..bce8fcd --- /dev/null +++ b/charts/irsa-manager/templates/manager-rbac.yaml @@ -0,0 +1,51 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "irsa-manager.fullname" . }}-manager-role + labels: + {{- include "irsa-manager.labels" . | nindent 4 }} +rules: +- apiGroups: + - irsa.kkb0318.github.io + resources: + - irsasetups + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - irsa.kkb0318.github.io + resources: + - irsasetups/finalizers + verbs: + - update +- apiGroups: + - irsa.kkb0318.github.io + resources: + - irsasetups/status + verbs: + - get + - patch + - update +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "irsa-manager.fullname" . }}-manager-rolebinding + labels: + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: irsa-manager + app.kubernetes.io/part-of: irsa-manager + {{- include "irsa-manager.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: '{{ include "irsa-manager.fullname" . }}-manager-role' +subjects: +- kind: ServiceAccount + name: '{{ include "irsa-manager.fullname" . }}-controller-manager' + namespace: '{{ .Release.Namespace }}' \ No newline at end of file diff --git a/charts/irsa-manager/templates/metrics-reader-rbac.yaml b/charts/irsa-manager/templates/metrics-reader-rbac.yaml new file mode 100644 index 0000000..0c4b4b3 --- /dev/null +++ b/charts/irsa-manager/templates/metrics-reader-rbac.yaml @@ -0,0 +1,14 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "irsa-manager.fullname" . }}-metrics-reader + labels: + app.kubernetes.io/component: kube-rbac-proxy + app.kubernetes.io/created-by: irsa-manager + app.kubernetes.io/part-of: irsa-manager + {{- include "irsa-manager.labels" . | nindent 4 }} +rules: +- nonResourceURLs: + - /metrics + verbs: + - get \ No newline at end of file diff --git a/charts/irsa-manager/templates/metrics-service.yaml b/charts/irsa-manager/templates/metrics-service.yaml new file mode 100644 index 0000000..bd6f773 --- /dev/null +++ b/charts/irsa-manager/templates/metrics-service.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "irsa-manager.fullname" . }}-controller-manager-metrics-service + labels: + app.kubernetes.io/component: kube-rbac-proxy + app.kubernetes.io/created-by: irsa-manager + app.kubernetes.io/part-of: irsa-manager + control-plane: controller-manager + {{- include "irsa-manager.labels" . | nindent 4 }} +spec: + type: {{ .Values.metricsService.type }} + selector: + control-plane: controller-manager + {{- include "irsa-manager.selectorLabels" . | nindent 4 }} + ports: + {{- .Values.metricsService.ports | toYaml | nindent 2 }} \ No newline at end of file diff --git a/charts/irsa-manager/templates/proxy-rbac.yaml b/charts/irsa-manager/templates/proxy-rbac.yaml new file mode 100644 index 0000000..dcdd466 --- /dev/null +++ b/charts/irsa-manager/templates/proxy-rbac.yaml @@ -0,0 +1,40 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "irsa-manager.fullname" . }}-proxy-role + labels: + app.kubernetes.io/component: kube-rbac-proxy + app.kubernetes.io/created-by: irsa-manager + app.kubernetes.io/part-of: irsa-manager + {{- include "irsa-manager.labels" . | nindent 4 }} +rules: +- apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create +- apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "irsa-manager.fullname" . }}-proxy-rolebinding + labels: + app.kubernetes.io/component: kube-rbac-proxy + app.kubernetes.io/created-by: irsa-manager + app.kubernetes.io/part-of: irsa-manager + {{- include "irsa-manager.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: '{{ include "irsa-manager.fullname" . }}-proxy-role' +subjects: +- kind: ServiceAccount + name: '{{ include "irsa-manager.fullname" . }}-controller-manager' + namespace: '{{ .Release.Namespace }}' \ No newline at end of file diff --git a/charts/irsa-manager/templates/serviceaccount.yaml b/charts/irsa-manager/templates/serviceaccount.yaml new file mode 100644 index 0000000..6ad5498 --- /dev/null +++ b/charts/irsa-manager/templates/serviceaccount.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "irsa-manager.fullname" . }}-controller-manager + labels: + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: irsa-manager + app.kubernetes.io/part-of: irsa-manager + {{- include "irsa-manager.labels" . | nindent 4 }} + annotations: + {{- toYaml .Values.controllerManager.serviceAccount.annotations | nindent 4 }} \ No newline at end of file diff --git a/charts/irsa-manager/values.yaml b/charts/irsa-manager/values.yaml new file mode 100644 index 0000000..05cdd74 --- /dev/null +++ b/charts/irsa-manager/values.yaml @@ -0,0 +1,53 @@ +controllerManager: + kubeRbacProxy: + args: + - --secure-listen-address=0.0.0.0:8443 + - --upstream=http://127.0.0.1:8080/ + - --logtostderr=true + - --v=0 + containerSecurityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + image: + repository: gcr.io/kubebuilder/kube-rbac-proxy + tag: v0.15.0 + resources: + limits: + cpu: 500m + memory: 128Mi + requests: + cpu: 5m + memory: 64Mi + manager: + args: + - --health-probe-bind-address=:8081 + - --metrics-bind-address=127.0.0.1:8080 + - --leader-elect + containerSecurityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + image: + repository: controller + tag: latest + resources: + limits: + cpu: 500m + memory: 128Mi + requests: + cpu: 10m + memory: 64Mi + replicas: 1 + serviceAccount: + annotations: {} +kubernetesClusterDomain: cluster.local +metricsService: + ports: + - name: https + port: 8443 + protocol: TCP + targetPort: https + type: ClusterIP diff --git a/config/release/kustomization.yaml b/config/release/kustomization.yaml new file mode 100644 index 0000000..995069e --- /dev/null +++ b/config/release/kustomization.yaml @@ -0,0 +1,4 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - ../default diff --git a/docs/api.md b/docs/api.md new file mode 100644 index 0000000..51432fb --- /dev/null +++ b/docs/api.md @@ -0,0 +1,120 @@ +# API Reference + +## Packages +- [irsa.kkb0318.github.io/v1alpha1](#irsakkb0318githubiov1alpha1) + + +## irsa.kkb0318.github.io/v1alpha1 + +Package v1alpha1 contains API Schema definitions for the irsa v1alpha1 API group + +### Resource Types +- [IRSASetup](#irsasetup) + + + +#### Auth + + + +Auth holds the authentication configuration details. + + + +_Appears in:_ +- [IRSASetupSpec](#irsasetupspec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `secretRef` _[SecretRef](#secretref)_ | SecretRef specifies the reference to the Kubernetes secret containing authentication details. | | | + + +#### Discovery + + + +Discovery holds the configuration for IdP Discovery, which is crucial for locating +the OIDC provider in a self-hosted environment. + + + +_Appears in:_ +- [IRSASetupSpec](#irsasetupspec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `s3` _[S3Discovery](#s3discovery)_ | S3 specifies the AWS S3 bucket details where the OIDC provider's discovery information is hosted. | | | + + +#### IRSASetup + + + +IRSASetup represents a configuration for setting up IAM Roles for Service Accounts (IRSA) in a Kubernetes cluster. + + + + + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `apiVersion` _string_ | `irsa.kkb0318.github.io/v1alpha1` | | | +| `kind` _string_ | `IRSASetup` | | | +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | +| `spec` _[IRSASetupSpec](#irsasetupspec)_ | | | | + + +#### IRSASetupSpec + + + +IRSASetupSpec defines the desired state of IRSASetup + + + +_Appears in:_ +- [IRSASetup](#irsasetup) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `mode` _string_ | Mode specifies the mode of operation. Can be either "selfhosted" or "eks". | | | +| `discovery` _[Discovery](#discovery)_ | Discovery configures the IdP Discovery process, essential for setting up IRSA by locating
the OIDC provider information. | | | +| `auth` _[Auth](#auth)_ | Auth contains authentication configuration details. | | | + + + + +#### S3Discovery + + + +S3Discovery contains the specifics of the S3 bucket used for hosting OIDC provider discovery information. + + + +_Appears in:_ +- [Discovery](#discovery) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `region` _string_ | Region denotes the AWS region where the S3 bucket is located. | | | +| `bucketName` _string_ | BucketName is the name of the S3 bucket that hosts the OIDC discovery information. | | | + + +#### SecretRef + + + +SecretRef contains the reference to a Kubernetes secret. + + + +_Appears in:_ +- [Auth](#auth) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `name` _string_ | Name specifies the name of the secret. | | | +| `namespace` _string_ | Namespace specifies the namespace of the secret. | | | + + diff --git a/docs/config.yaml b/docs/config.yaml new file mode 100644 index 0000000..b6ff483 --- /dev/null +++ b/docs/config.yaml @@ -0,0 +1,9 @@ +processor: + ignoreTypes: + - "List$" + ignoreFields: + - "status$" + - "TypeMeta$" + +render: + kubernetesVersion: 1.28 diff --git a/internal/client/aws.go b/internal/client/aws.go index 716f389..b3538fc 100644 --- a/internal/client/aws.go +++ b/internal/client/aws.go @@ -45,7 +45,7 @@ type AwsS3Client struct { client *s3.Client } -func (a *AwsS3Client) PutObject(ctx context.Context, key string, body []byte) error { +func (a *AwsS3Client) PutObjectPublic(ctx context.Context, key string, body []byte) error { _, err := a.client.PutObject(ctx, &s3.PutObjectInput{ Bucket: aws.String(a.bucketName), Key: aws.String(key), @@ -56,7 +56,7 @@ func (a *AwsS3Client) PutObject(ctx context.Context, key string, body []byte) er return err } -func (a *AwsS3Client) CreateBucket(ctx context.Context) error { +func (a *AwsS3Client) CreateBucketPublic(ctx context.Context) error { bucket := aws.String(a.bucketName) _, err := a.client.CreateBucket(ctx, &s3.CreateBucketInput{ Bucket: bucket, @@ -84,23 +84,9 @@ func (a *AwsS3Client) CreateBucket(ctx context.Context) error { if err != nil { return err } - // _, err = a.client.PutBucketAcl(ctx, &s3.PutBucketAclInput{ - // Bucket: bucket, - // ACL: types.BucketCannedACLPublicRead, - // }) - // if err != nil { - // return err - // } return nil } -func (a *AwsS3Client) PutBucketOwnershipControls(ctx context.Context) error { - _, err := a.client.PutBucketOwnershipControls(ctx, &s3.PutBucketOwnershipControlsInput{ - Bucket: aws.String(a.bucketName), - }) - return err -} - func (a *AwsS3Client) BucketName() string { return a.bucketName }