Skip to content
This repository was archived by the owner on Jan 16, 2023. It is now read-only.

SRE-3688: create posrgresql db user operator #1

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
collections
15 changes: 15 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
FROM quay.io/operator-framework/ansible-operator:v1.0.1

USER 0
RUN dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-8-x86_64/pgdg-redhat-repo-latest.noarch.rpm
RUN dnf install -y libpq5-devel
RUN pip3 install psycopg2-binary
USER 1001

COPY requirements.yml ${HOME}/requirements.yml
RUN ansible-galaxy collection install -r ${HOME}/requirements.yml \
&& chmod -R ug+rwx ${HOME}/.ansible

COPY watches.yaml ${HOME}/watches.yaml
COPY roles/ ${HOME}/roles/
COPY playbooks/ ${HOME}/playbooks/
92 changes: 92 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Current Operator version
VERSION ?= 0.0.1
# Default bundle image tag
BUNDLE_IMG ?= controller-bundle:$(VERSION)
# Options for 'bundle-build'
ifneq ($(origin CHANNELS), undefined)
BUNDLE_CHANNELS := --channels=$(CHANNELS)
endif
ifneq ($(origin DEFAULT_CHANNEL), undefined)
BUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL)
endif
BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL)

# Image URL to use all building/pushing image targets
IMG ?= controller:latest

all: docker-build

# Run against the configured Kubernetes cluster in ~/.kube/config
run: ansible-operator
$(ANSIBLE_OPERATOR) run

# Install CRDs into a cluster
install: kustomize
$(KUSTOMIZE) build config/crd | kubectl apply -f -

# Uninstall CRDs from a cluster
uninstall: kustomize
$(KUSTOMIZE) build config/crd | kubectl delete -f -

# Deploy controller in the configured Kubernetes cluster in ~/.kube/config
deploy: kustomize
cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
$(KUSTOMIZE) build config/default | kubectl apply -f -

# Undeploy controller in the configured Kubernetes cluster in ~/.kube/config
undeploy: kustomize
$(KUSTOMIZE) build config/default | kubectl delete -f -

# Build the docker image
docker-build:
docker build . -t ${IMG}

# Push the docker image
docker-push:
docker push ${IMG}

PATH := $(PATH):$(PWD)/bin
SHELL := env PATH=$(PATH) /bin/sh
OS = $(shell uname -s | tr '[:upper:]' '[:lower:]')
ARCH = $(shell uname -m | sed 's/x86_64/amd64/')
OSOPER = $(shell uname -s | tr '[:upper:]' '[:lower:]' | sed 's/darwin/apple-darwin/' | sed 's/linux/linux-gnu/')
ARCHOPER = $(shell uname -m )

kustomize:
ifeq (, $(shell which kustomize 2>/dev/null))
@{ \
set -e ;\
mkdir -p bin ;\
curl -sSLo - https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/v3.5.4/kustomize_v3.5.4_$(OS)_$(ARCH).tar.gz | tar xzf - -C bin/ ;\
}
KUSTOMIZE=$(realpath ./bin/kustomize)
else
KUSTOMIZE=$(shell which kustomize)
endif

ansible-operator:
ifeq (, $(shell which ansible-operator 2>/dev/null))
@{ \
set -e ;\
mkdir -p bin ;\
curl -LO https://github.com/operator-framework/operator-sdk/releases/download/v1.0.1/ansible-operator-v1.0.1-$(ARCHOPER)-$(OSOPER) ;\
mv ansible-operator-v1.0.1-$(ARCHOPER)-$(OSOPER) ./bin/ansible-operator ;\
chmod +x ./bin/ansible-operator ;\
}
ANSIBLE_OPERATOR=$(realpath ./bin/ansible-operator)
else
ANSIBLE_OPERATOR=$(shell which ansible-operator)
endif

# Generate bundle manifests and metadata, then validate generated files.
.PHONY: bundle
bundle: kustomize
operator-sdk generate kustomize manifests -q
cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG)
$(KUSTOMIZE) build config/manifests | operator-sdk generate bundle -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS)
operator-sdk bundle validate ./bundle

# Build the bundle image.
.PHONY: bundle-build
bundle-build:
docker build -f bundle.Dockerfile -t $(BUNDLE_IMG) .
8 changes: 8 additions & 0 deletions PROJECT
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
domain: takeoff.io
layout: ansible.sdk.operatorframework.io/v1
projectName: pgsql-db-user-manager
resources:
- group: pgsql
kind: ReadOnlyDBUser
version: v1alpha1
version: 3-alpha
40 changes: 38 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,38 @@
# pgsql-db-user-manager-operator
A Kubernetes operator to manage postgresql users and permissions
# PostgreSQL database user manager operator for kubernetes

## Features
* Create a user with read-only access to a single database

## Installation
Unknown at this time

## CRs

### ReadOnlyDBUser
```yaml
apiVersion: pgsql.takeoff.io/v1alpha1
kind: ReadOnlyDBUser
metadata:
name: testdbrouser # name of dbuser to create
spec:
db_name: testdb # name of database to give select, use (readonly) access to
password:
value: string # password value in plaintxt
valueFrom: # get the password from a kubernetes secret object
secretKeyRef:
key: string
name: string
pghost: cloudsql-postgres # host to connect to
pguser: postgres # admin user to connect and create user as
pgpass: donotuseme1234 # password for admin user
```

This creates a user called `testdbrouser` with a password of `changeme1234` and is given read-only access to `testdb`.
It performs the same operations as these SQL statements:
1. \connect postgres
2. CREATE USER testdbrouser WITH PASSWORD 'changeme1234'
3. \connect testdb
4. GRANT USAGE ON SCHEMA public TO testdbrouser
5. GRANT SELECT ON ALL TABLES IN SCHEMA public TO testdbrouser
6. ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO testdbrouser
>>>>>>> 3ef00b5... initial working MVP
44 changes: 44 additions & 0 deletions config/crd/bases/pgsql.takeoff.io_readonlydbusers.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: readonlydbusers.pgsql.takeoff.io
spec:
group: pgsql.takeoff.io
names:
kind: ReadOnlyDBUser
listKind: ReadOnlyDBUserList
plural: readonlydbusers
singular: readonlydbuser
scope: Namespaced
versions:
- name: v1alpha1
schema:
openAPIV3Schema:
description: ReadOnlyDBUser is the Schema for the readonlydbusers API
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: Spec defines the desired state of ReadOnlyDBUser
type: object
x-kubernetes-preserve-unknown-fields: true
status:
description: Status defines the observed state of ReadOnlyDBUser
type: object
x-kubernetes-preserve-unknown-fields: true
type: object
served: true
storage: true
subresources:
status: {}
6 changes: 6 additions & 0 deletions config/crd/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# This kustomization.yaml is not intended to be run by itself,
# since it depends on service name and namespace that are out of this kustomize package.
# It should be run by config/default
resources:
- bases/pgsql.takeoff.io_readonlydbusers.yaml
# +kubebuilder:scaffold:crdkustomizeresource
26 changes: 26 additions & 0 deletions config/default/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Adds namespace to all resources.
namespace: pgsql-db-user-manager-system

# Value of this field is prepended to the
# names of all resources, e.g. a deployment named
# "wordpress" becomes "alices-wordpress".
# Note that it should also match with the prefix (text before '-') of the namespace
# field above.
namePrefix: pgsql-db-user-manager-

# Labels to add to all resources and selectors.
#commonLabels:
# someName: someValue

bases:
- ../crd
- ../rbac
- ../manager
# [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'.
#- ../prometheus

patchesStrategicMerge:
# Protect the /metrics endpoint by putting it behind auth.
# If you want your controller-manager to expose the /metrics
# endpoint w/o any authn/z, please comment the following line.
- manager_auth_proxy_patch.yaml
26 changes: 26 additions & 0 deletions config/default/manager_auth_proxy_patch.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# This patch inject a sidecar container which is a HTTP proxy for the
# controller manager, it performs RBAC authorization against the Kubernetes API using SubjectAccessReviews.
apiVersion: apps/v1
kind: Deployment
metadata:
name: controller-manager
namespace: system
spec:
template:
spec:
containers:
- name: kube-rbac-proxy
image: gcr.io/kubebuilder/kube-rbac-proxy:v0.5.0
args:
- "--secure-listen-address=0.0.0.0:8443"
- "--upstream=http://127.0.0.1:8080/"
- "--logtostderr=true"
- "--v=10"
ports:
- containerPort: 8443
name: https
- name: manager
args:
- "--metrics-addr=127.0.0.1:8080"
- "--enable-leader-election"
- "--leader-election-id=pgsql-db-user-manager"
4 changes: 4 additions & 0 deletions config/manager/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
resources:
- manager.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
31 changes: 31 additions & 0 deletions config/manager/manager.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
apiVersion: v1
kind: Namespace
metadata:
labels:
control-plane: controller-manager
name: system
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: controller-manager
namespace: system
labels:
control-plane: controller-manager
spec:
selector:
matchLabels:
control-plane: controller-manager
replicas: 1
template:
metadata:
labels:
control-plane: controller-manager
spec:
containers:
- name: manager
args:
- "--enable-leader-election"
- "--leader-election-id=pgsql-db-user-manager"
image: controller:latest
terminationGracePeriodSeconds: 10
2 changes: 2 additions & 0 deletions config/prometheus/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
resources:
- monitor.yaml
16 changes: 16 additions & 0 deletions config/prometheus/monitor.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
# Prometheus Monitor Service (Metrics)
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
labels:
control-plane: controller-manager
name: controller-manager-metrics-monitor
namespace: system
spec:
endpoints:
- path: /metrics
port: https
selector:
matchLabels:
control-plane: controller-manager
7 changes: 7 additions & 0 deletions config/rbac/auth_proxy_client_clusterrole.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: metrics-reader
rules:
- nonResourceURLs: ["/metrics"]
verbs: ["get"]
13 changes: 13 additions & 0 deletions config/rbac/auth_proxy_role.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: proxy-role
rules:
- apiGroups: ["authentication.k8s.io"]
resources:
- tokenreviews
verbs: ["create"]
- apiGroups: ["authorization.k8s.io"]
resources:
- subjectaccessreviews
verbs: ["create"]
12 changes: 12 additions & 0 deletions config/rbac/auth_proxy_role_binding.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: proxy-rolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: proxy-role
subjects:
- kind: ServiceAccount
name: default
namespace: system
14 changes: 14 additions & 0 deletions config/rbac/auth_proxy_service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
apiVersion: v1
kind: Service
metadata:
labels:
control-plane: controller-manager
name: controller-manager-metrics-service
namespace: system
spec:
ports:
- name: https
port: 8443
targetPort: https
selector:
control-plane: controller-manager
12 changes: 12 additions & 0 deletions config/rbac/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
resources:
- role.yaml
- role_binding.yaml
- leader_election_role.yaml
- leader_election_role_binding.yaml
# Comment the following 4 lines if you want to disable
# the auth proxy (https://github.com/brancz/kube-rbac-proxy)
# which protects your /metrics endpoint.
- auth_proxy_service.yaml
- auth_proxy_role.yaml
- auth_proxy_role_binding.yaml
- auth_proxy_client_clusterrole.yaml
Loading