diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..87a336e06 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +env +helm +passbook-ui diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..d51d5af73 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,17 @@ +FROM python:3.6-slim-stretch +# LABEL version="1.8.8" + +COPY ./passbook/ /app/passbook +COPY ./static/ /app/static +COPY ./manage.py /app/ +COPY ./requirements.txt /app/ + +WORKDIR /app/ + +#RUN apk add --no-cache libffi-dev build-base py2-pip python2-dev libxml-dev && \ +RUN pip install -r requirements.txt && \ + pip install psycopg2 && \ + adduser --system --home /app/ passbook && \ + chown -R passbook /app/ + +USER passbook diff --git a/helm/passbook/.helmignore b/helm/passbook/.helmignore new file mode 100644 index 000000000..f0c131944 --- /dev/null +++ b/helm/passbook/.helmignore @@ -0,0 +1,21 @@ +# 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 +*~ +# Various IDEs +.project +.idea/ +*.tmproj diff --git a/helm/passbook/Chart.yaml b/helm/passbook/Chart.yaml new file mode 100644 index 000000000..3cac5c5df --- /dev/null +++ b/helm/passbook/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +appVersion: "1.0.0" +description: A Helm chart for passbook. +name: passbook +version: 1.0.0 +icon: https://passbook.beryju.org/images/logo.png diff --git a/helm/passbook/charts/postgresql-3.10.1.tgz b/helm/passbook/charts/postgresql-3.10.1.tgz new file mode 100644 index 000000000..04e30b263 Binary files /dev/null and b/helm/passbook/charts/postgresql-3.10.1.tgz differ diff --git a/helm/passbook/charts/redis-5.1.0.tgz b/helm/passbook/charts/redis-5.1.0.tgz new file mode 100644 index 000000000..71237425a Binary files /dev/null and b/helm/passbook/charts/redis-5.1.0.tgz differ diff --git a/helm/passbook/requirements.lock b/helm/passbook/requirements.lock new file mode 100644 index 000000000..8457a7c56 --- /dev/null +++ b/helm/passbook/requirements.lock @@ -0,0 +1,9 @@ +dependencies: +- name: redis + repository: https://kubernetes-charts.storage.googleapis.com/ + version: 5.1.0 +- name: postgresql + repository: https://kubernetes-charts.storage.googleapis.com/ + version: 3.10.1 +digest: sha256:04bd136761f070e94a2ff32ff48ff87f5e07fbd451e5fd7f65551e3bd4680e5e +generated: 2019-02-08T12:08:49.090666+01:00 diff --git a/helm/passbook/requirements.yaml b/helm/passbook/requirements.yaml new file mode 100644 index 000000000..0d5a7feea --- /dev/null +++ b/helm/passbook/requirements.yaml @@ -0,0 +1,7 @@ +dependencies: +- name: redis + version: 5.1.0 + repository: https://kubernetes-charts.storage.googleapis.com/ +- name: postgresql + version: 3.10.1 + repository: https://kubernetes-charts.storage.googleapis.com/ diff --git a/helm/passbook/templates/NOTES.txt b/helm/passbook/templates/NOTES.txt new file mode 100644 index 000000000..99ea21d12 --- /dev/null +++ b/helm/passbook/templates/NOTES.txt @@ -0,0 +1,19 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range .Values.ingress.hosts }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ . }}{{ $.Values.ingress.path }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "passbook.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get svc -w {{ include "passbook.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "passbook.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "passbook.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl port-forward $POD_NAME 8080:8000 +{{- end }} diff --git a/helm/passbook/templates/_helpers.tpl b/helm/passbook/templates/_helpers.tpl new file mode 100644 index 000000000..e07a252d0 --- /dev/null +++ b/helm/passbook/templates/_helpers.tpl @@ -0,0 +1,32 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "passbook.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 "passbook.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 "passbook.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} diff --git a/helm/passbook/templates/passbook-configmap.yaml b/helm/passbook/templates/passbook-configmap.yaml new file mode 100644 index 000000000..314e31f0d --- /dev/null +++ b/helm/passbook/templates/passbook-configmap.yaml @@ -0,0 +1,138 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "passbook.fullname" . }}-config +data: + config.yml: | + # Env for Docker images + databases: + default: + engine: django.db.backends.postgresql + name: {{ .Values.postgresql.postgresqlDatabase }} + user: postgres + password: {{ .Values.postgresql.postgresqlPassword }} + host: {{ .Release.Name }}-postgresql + port: '' + log: + level: + console: DEBUG + file: DEBUG + file: /dev/null + syslog: + host: 127.0.0.1 + port: 514 + email: + host: localhost + port: 25 + user: '' + password: '' + use_tls: false + use_ssl: false + from: passbook + web: + listen: 0.0.0.0 + port: 8000 + threads: 30 + debug: false + secure_proxy_header: + HTTP_X_FORWARDED_PROTO: https + redis: {{ .Release.Name }}-redis + # Error reporting, sends stacktrace to sentry.services.beryju.org + error_report_enabled: {{ .Values.config.error_reporting }} + + {{- if .Values.config.secret_key }} + secret_key: {{ .Values.config.secret_key }} + {{- else }} + secret_key: {{ randAlphaNum 50 }} + {{- end }} + + domains: + {{- range .Values.ingress.hosts }} + - {{ . | quote }} + {{- end }} + + passbook: + sign_up: + # Enables signup, created users are stored in internal Database and created in LDAP if ldap.create_users is true + enabled: true + password_reset: + # Enable password reset, passwords are reset in internal Database and in LDAP if ldap.reset_password is true + enabled: true + # Verification the user has to provide in order to be able to reset passwords. Can be any combination of `email`, `2fa`, `security_questions` + verification: + - email + # Text used in title, on login page and multiple other places + branding: passbook + login: + # Override URL used for logo + logo_url: null + # Override URL used for Background on Login page + bg_url: null + # Optionally add a subtext, placed below logo on the login page + subtext: null + footer: + links: + # Optionally add links to the footer on the login page + # - name: test + # href: https://test + # Specify which fields can be used to authenticate. Can be any combination of `username` and `email` + uid_fields: + - username + - email + session: + remember_age: 2592000 # 60 * 60 * 24 * 30, one month + # Provider-specific settings + ldap: + # # Completely enable or disable LDAP provider + # enabled: false + # # AD Domain, used to generate `userPrincipalName` + # domain: corp.contoso.com + # # Base DN in which passbook should look for users + # base_dn: dn=corp,dn=contoso,dn=com + # # LDAP field which is used to set the django username + # username_field: sAMAccountName + # # LDAP server to connect to, can be set to `` + # server: + # name: corp.contoso.com + # use_tls: false + # # Bind credentials, used for account creation + # bind: + # username: Administraotr@corp.contoso.com + # password: VerySecurePassword! + # Which field from `uid_fields` maps to which LDAP Attribute + login_field_map: + username: sAMAccountName + email: mail # or userPrincipalName + user_attribute_map: + active_directory: + sAMAccountName: username + mail: email + given_name: first_name + name: last_name + # # Create new users in LDAP upon sign-up + # create_users: true + # # Reset LDAP password when user reset their password + # reset_password: true + oauth_client: + # List of python packages with sources types to load. + types: + - passbook.oauth_client.source_types.discord + - passbook.oauth_client.source_types.facebook + - passbook.oauth_client.source_types.github + - passbook.oauth_client.source_types.google + - passbook.oauth_client.source_types.reddit + - passbook.oauth_client.source_types.supervisr + - passbook.oauth_client.source_types.twitter + saml_idp: + signing: true + autosubmit: false + issuer: passbook + assertion_valid_for: 86400 + # List of python packages with provider types to load. + types: + - passbook.saml_idp.processors.generic + - passbook.saml_idp.processors.gitlab + - passbook.saml_idp.processors.nextcloud + - passbook.saml_idp.processors.salesforce + - passbook.saml_idp.processors.shibboleth + - passbook.saml_idp.processors.wordpress_orange diff --git a/helm/passbook/templates/passbook-web-deployment.yaml b/helm/passbook/templates/passbook-web-deployment.yaml new file mode 100644 index 000000000..78830221d --- /dev/null +++ b/helm/passbook/templates/passbook-web-deployment.yaml @@ -0,0 +1,66 @@ +apiVersion: apps/v1beta2 +kind: Deployment +metadata: + name: {{ include "passbook.fullname" . }}-web + labels: + app.kubernetes.io/name: {{ include "passbook.name" . }} + helm.sh/chart: {{ include "passbook.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + app.kubernetes.io/name: {{ include "passbook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + template: + metadata: + labels: + app.kubernetes.io/name: {{ include "passbook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + spec: + volumes: + - name: config-volume + configMap: + name: {{ include "passbook.fullname" . }}-config + containers: + - name: {{ .Chart.Name }} + image: "docker.pkg.beryju.org/passbook:{{ .Values.image.tag }}" + imagePullPolicy: IfNotPresent + command: ["/bin/sh","-c"] + args: ["./manage.py migrate && ./manage.py web"] + ports: + - name: http + containerPort: 8000 + protocol: TCP + volumeMounts: + - mountPath: /etc/passbook + name: config-volume + livenessProbe: + httpGet: + path: / + port: http + httpHeaders: + - name: Host + value: kubernetes-healthcheck-host + readinessProbe: + httpGet: + path: / + port: http + httpHeaders: + - name: Host + value: kubernetes-healthcheck-host + resources: +{{ toYaml .Values.resources | indent 12 }} + {{- with .Values.nodeSelector }} + nodeSelector: +{{ toYaml . | indent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: +{{ toYaml . | indent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: +{{ toYaml . | indent 8 }} + {{- end }} diff --git a/helm/passbook/templates/passbook-web-ingress.yaml b/helm/passbook/templates/passbook-web-ingress.yaml new file mode 100644 index 000000000..0ff329cce --- /dev/null +++ b/helm/passbook/templates/passbook-web-ingress.yaml @@ -0,0 +1,38 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "passbook.fullname" . -}} +{{- $ingressPath := .Values.ingress.path -}} +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + app.kubernetes.io/name: {{ include "passbook.name" . }} + helm.sh/chart: {{ include "passbook.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- with .Values.ingress.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: +{{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} +{{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ . | quote }} + http: + paths: + - path: {{ $ingressPath }} + backend: + serviceName: {{ $fullName }} + servicePort: http + {{- end }} +{{- end }} diff --git a/helm/passbook/templates/passbook-web-service.yaml b/helm/passbook/templates/passbook-web-service.yaml new file mode 100644 index 000000000..1cbb65de6 --- /dev/null +++ b/helm/passbook/templates/passbook-web-service.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "passbook.fullname" . }} + labels: + app.kubernetes.io/name: {{ include "passbook.name" . }} + helm.sh/chart: {{ include "passbook.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + app.kubernetes.io/name: {{ include "passbook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} diff --git a/helm/passbook/templates/passbook-worker-deployment.yaml b/helm/passbook/templates/passbook-worker-deployment.yaml new file mode 100644 index 000000000..f4b6c8513 --- /dev/null +++ b/helm/passbook/templates/passbook-worker-deployment.yaml @@ -0,0 +1,51 @@ +apiVersion: apps/v1beta2 +kind: Deployment +metadata: + name: {{ include "passbook.fullname" . }}-worker + labels: + app.kubernetes.io/name: {{ include "passbook.name" . }} + helm.sh/chart: {{ include "passbook.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + app.kubernetes.io/name: {{ include "passbook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + template: + metadata: + labels: + app.kubernetes.io/name: {{ include "passbook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + spec: + volumes: + - name: config-volume + configMap: + name: {{ include "passbook.fullname" . }}-config + containers: + - name: {{ .Chart.Name }} + image: "docker.pkg.beryju.org/passbook:{{ .Values.image.tag }}" + imagePullPolicy: IfNotPresent + command: ["./manage.py", "worker"] + ports: + - name: http + containerPort: 8000 + protocol: TCP + volumeMounts: + - mountPath: /etc/passbook + name: config-volume + resources: +{{ toYaml .Values.resources | indent 12 }} + {{- with .Values.nodeSelector }} + nodeSelector: +{{ toYaml . | indent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: +{{ toYaml . | indent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: +{{ toYaml . | indent 8 }} + {{- end }} diff --git a/helm/passbook/values.yaml b/helm/passbook/values.yaml new file mode 100644 index 000000000..ef8f52287 --- /dev/null +++ b/helm/passbook/values.yaml @@ -0,0 +1,57 @@ +# Default values for passbook. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + tag: latest + +nameOverride: "" + +config: + # Optionally specify fixed secret_key, otherwise generated automatically + # secret_key: _k*@6h2u2@q-dku57hhgzb7tnx*ba9wodcb^s9g0j59@=y(@_o + # Enable error reporting + error_reporting: true + +postgresql: + postgresqlDatabase: passbook + postgresqlPassword: foo + +service: + type: ClusterIP + port: 80 + +ingress: + enabled: false + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + path: / + hosts: + - passbook.k8s.local + - kubernetes-healthcheck-host + defaultHost: passbook.k8s.local + tls: [] + # - secretName: chart-example-tls + # hosts: + # - passbook.k8s.local + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +nodeSelector: {} + +tolerations: [] + +affinity: {}