diff --git a/docs/integrations/platforms/kubernetes.mdx b/docs/integrations/platforms/kubernetes.mdx index a925f6c4b..6defea119 100644 --- a/docs/integrations/platforms/kubernetes.mdx +++ b/docs/integrations/platforms/kubernetes.mdx @@ -41,6 +41,30 @@ The operator can be install via [Helm](https://helm.sh) or [kubectl](https://git helm install --generate-name infisical-helm-charts/secrets-operator --version=0.1.4 --set controllerManager.manager.image.tag=v0.2.0 ``` + **Namespace-scoped Installation** + + The operator can be configured to watch and manage secrets in a specific namespace instead of having cluster-wide access. + + ```bash + helm install operator infisical-helm-charts/secrets-operator \ + --namespace your-namespace \ + --set scopedNamespace=your-namespace \ + --set scopedRBAC=true + ``` + + When scoped to a namespace, the operator will: + + - Only watch InfisicalSecrets in the specified namespace + - Only create/update Kubernetes secrets in that namespace + - Only access deployments in that namespace + + The default configuration gives cluster-wide access: + + ```yaml + scopedNamespace: "" # Empty for cluster-wide access + scopedRBAC: false # Cluster-wide permissions + ``` + For production deployments, it is highly recommended to set the version of the Kubernetes operator manually instead of pointing to the latest version. diff --git a/helm-charts/secrets-operator/Chart.yaml b/helm-charts/secrets-operator/Chart.yaml index f212ce4eb..ca6747984 100644 --- a/helm-charts/secrets-operator/Chart.yaml +++ b/helm-charts/secrets-operator/Chart.yaml @@ -13,9 +13,9 @@ 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: v0.7.5 +version: v0.7.6 # 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: "v0.7.5" +appVersion: "v0.7.6" diff --git a/helm-charts/secrets-operator/templates/deployment.yaml b/helm-charts/secrets-operator/templates/deployment.yaml index ec02df12d..e67db7b3f 100644 --- a/helm-charts/secrets-operator/templates/deployment.yaml +++ b/helm-charts/secrets-operator/templates/deployment.yaml @@ -54,7 +54,11 @@ spec: 10 }} securityContext: {{- toYaml .Values.controllerManager.kubeRbacProxy.containerSecurityContext | nindent 10 }} - - args: {{- toYaml .Values.controllerManager.manager.args | nindent 8 }} + - args: + {{- toYaml .Values.controllerManager.manager.args | nindent 8 }} + {{- if and .Values.scopedNamespace .Values.scopedRBAC }} + - --namespace={{ .Values.scopedNamespace }} + {{- end }} command: - /manager env: diff --git a/helm-charts/secrets-operator/templates/manager-rbac.yaml b/helm-charts/secrets-operator/templates/manager-rbac.yaml index ca6fd36e1..33f00198f 100644 --- a/helm-charts/secrets-operator/templates/manager-rbac.yaml +++ b/helm-charts/secrets-operator/templates/manager-rbac.yaml @@ -1,7 +1,14 @@ apiVersion: rbac.authorization.k8s.io/v1 +{{- if and .Values.scopedNamespace .Values.scopedRBAC }} +kind: Role +{{- else }} kind: ClusterRole +{{- end }} metadata: name: {{ include "secrets-operator.fullname" . }}-manager-role + {{- if and .Values.scopedNamespace .Values.scopedRBAC }} + namespace: {{ .Values.scopedNamespace | quote }} + {{- end }} labels: {{- include "secrets-operator.labels" . | nindent 4 }} rules: @@ -72,9 +79,16 @@ rules: - update --- apiVersion: rbac.authorization.k8s.io/v1 +{{- if and .Values.scopedNamespace .Values.scopedRBAC }} +kind: RoleBinding +{{- else }} kind: ClusterRoleBinding +{{- end }} metadata: name: {{ include "secrets-operator.fullname" . }}-manager-rolebinding + {{- if and .Values.scopedNamespace .Values.scopedRBAC }} + namespace: {{ .Values.scopedNamespace | quote }} + {{- end }} labels: app.kubernetes.io/component: rbac app.kubernetes.io/created-by: k8-operator @@ -82,7 +96,11 @@ metadata: {{- include "secrets-operator.labels" . | nindent 4 }} roleRef: apiGroup: rbac.authorization.k8s.io + {{- if and .Values.scopedNamespace .Values.scopedRBAC }} + kind: Role + {{- else }} kind: ClusterRole + {{- end }} name: '{{ include "secrets-operator.fullname" . }}-manager-role' subjects: - kind: ServiceAccount diff --git a/helm-charts/secrets-operator/values.yaml b/helm-charts/secrets-operator/values.yaml index dc342c5ac..82668c5a4 100644 --- a/helm-charts/secrets-operator/values.yaml +++ b/helm-charts/secrets-operator/values.yaml @@ -1,15 +1,15 @@ controllerManager: kubeRbacProxy: args: - - --secure-listen-address=0.0.0.0:8443 - - --upstream=http://127.0.0.1:8080/ - - --logtostderr=true - - --v=0 + - --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 + - ALL image: repository: gcr.io/kubebuilder/kube-rbac-proxy tag: v0.15.0 @@ -22,17 +22,17 @@ controllerManager: memory: 64Mi manager: args: - - --health-probe-bind-address=:8081 - - --metrics-bind-address=127.0.0.1:8080 - - --leader-elect + - --health-probe-bind-address=:8081 + - --metrics-bind-address=127.0.0.1:8080 + - --leader-elect containerSecurityContext: allowPrivilegeEscalation: false capabilities: drop: - - ALL + - ALL image: repository: infisical/kubernetes-operator - tag: v0.7.5 + tag: v0.7.6 resources: limits: cpu: 500m @@ -46,10 +46,12 @@ controllerManager: nodeSelector: {} tolerations: [] kubernetesClusterDomain: cluster.local +scopedNamespace: "" +scopedRBAC: false metricsService: ports: - - name: https - port: 8443 - protocol: TCP - targetPort: https + - name: https + port: 8443 + protocol: TCP + targetPort: https type: ClusterIP diff --git a/k8-operator/main.go b/k8-operator/main.go index 50c0cda00..4fb64c7f4 100644 --- a/k8-operator/main.go +++ b/k8-operator/main.go @@ -36,8 +36,10 @@ func main() { var metricsAddr string var enableLeaderElection bool var probeAddr string + var namespace string flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.") flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.") + flag.StringVar(&namespace, "namespace", "", "Watch InfisicalSecrets scoped in the provided namespace only") flag.BoolVar(&enableLeaderElection, "leader-elect", false, "Enable leader election for controller manager. "+ "Enabling this will ensure there is only one active controller manager.") @@ -49,7 +51,7 @@ func main() { ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts))) - mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ + ctrlOpts := ctrl.Options{ Scheme: scheme, MetricsBindAddress: metricsAddr, Port: 9443, @@ -67,7 +69,13 @@ func main() { // if you are doing or is intended to do any operation such as perform cleanups // after the manager stops then its usage might be unsafe. // LeaderElectionReleaseOnCancel: true, - }) + } + + if namespace != "" { + ctrlOpts.Namespace = namespace + } + + mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrlOpts) if err != nil { setupLog.Error(err, "unable to start manager") os.Exit(1)