From 932563510a4f32f58782b1fe4738a0d2006e010f Mon Sep 17 00:00:00 2001
From: Ricardo Rocha <rocha.porto@gmail.com>
Date: Mon, 20 Jan 2020 16:57:40 +0100
Subject: [PATCH] Add sample application for gitops

---
 README.md                                     | 102 ++++++++++--------
 charts/gitops-getting-started/Chart.yaml      |   4 +
 .../gitops-getting-started/requirements.yaml  |   4 +
 .../gitops-getting-started/templates/psp.yaml |  91 ++++++++++++++++
 charts/gitops-getting-started/values.yaml     |  21 ++++
 flux-values.yaml                              |   6 ++
 helm-operator-values.yaml                     |  13 +++
 namespaces/prod.yaml                          |   5 +
 namespaces/stg.yaml                           |   5 +
 releases/prod/values.yaml                     |  27 +++++
 releases/stg/values.yaml                      |  27 +++++
 secrets/prod/secrets.yaml                     |  14 +++
 secrets/stg/secrets.yaml                      |  14 +++
 13 files changed, 286 insertions(+), 47 deletions(-)
 create mode 100644 charts/gitops-getting-started/Chart.yaml
 create mode 100644 charts/gitops-getting-started/requirements.yaml
 create mode 100644 charts/gitops-getting-started/templates/psp.yaml
 create mode 100644 charts/gitops-getting-started/values.yaml
 create mode 100644 flux-values.yaml
 create mode 100644 helm-operator-values.yaml
 create mode 100644 namespaces/prod.yaml
 create mode 100644 namespaces/stg.yaml
 create mode 100644 releases/prod/values.yaml
 create mode 100644 releases/stg/values.yaml
 create mode 100644 secrets/prod/secrets.yaml
 create mode 100644 secrets/stg/secrets.yaml

diff --git a/README.md b/README.md
index f4020c5..3ccea18 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,14 @@
 # GitOps Getting Started
 
-This repo acts as an example to manage application deployment and configuration
-using GitOps and the tool Flux.
+An example of an application deployment and configuration managed using GitOps
+and the tool Flux.
 
-The sample application has two parts:
-* a frontend based on wordpress
+The goal is to have a central git repo hosting all the configuration and
+deployments for an application, including its dependencies. Permissions set in
+this repo also define who is allowed to update the configuration.
+
+This example has two main components:
+* a frontend web application based on wordpress
 * a backend MySQL database 
 
 It should be enough to give you hints on how to manage your own deployments in
@@ -32,70 +36,74 @@ see what goes in these resources.
 ## Structure and Releases
 
 The structure of this repo is as follows:
-* **chart**: the umbrella chart, with defaults and any extra setup required
+* **chart**: the umbrella chart. These is where all the default configuration
+  for the dependencies is stored, inside the values.yaml file. You can also add
+  custom manifests under the templates directory
+* **namespaces**: Flux expects all the required namespaces to be defined here.
+  In this example we have both *prod* and *stg*
 * **releases**: the different deployments of the application (staging, production),
-each with overrides or complements of the default values. These are defined as
-Flux HelmRelease resources
+  each with overrides for the configuration as required - completing the default
+  values. These are Flux HelmRelease resources
+* **secrets**: this is a special directory that is not part of standard Flux. In
+  the future it will not be required, but for now it holds the parts of the
+  values yaml definitions that are sensitive (and require encryption to be
+  safely committed to git)
 
 ## Secrets
 
-Secrets are stored along the release values, but encrypted using the [helm
-secrets](https://gitlab.cern.ch/helm/plugins/barbican) plugin - this makes them
-also version controlled.
-
-To achieve this it means that for the moment they are not managed by Flux, a
-better integration will appear later.
+We recommend using the [helm secrets](https://gitlab.cern.ch/helm/plugins/barbican)
+plugin to encrypt the files under the *secrets* directory.
 
-You need to do the following once before installing flux:
+As Flux does not understand this encryption method, we need to create these
+secrets in advance, following something like:
 ```bash
-kubectl -n hub create -f releases/prod/hub-secrets.yaml
-kubectl -n hub-stg create -f releases/stg/hub-secrets.yaml
+kubectl create namespace prod
+kubectl create namespace stg
+
+kubectl create -f secrets/prod/secrets.yaml
+kubectl create -f secrets/stg/secrets.yaml
 ```
 
-and update them manually everytime when you update secrets.
+Remember that these resources are not managed by Flux. If you need to update
+any part of the sensitive values yaml data, you need to update them manually
+by doing:
+```
+kubectl apply -f secrets/prod/secrets.yaml
+kubectl apply -f secrets/stg/secrets.yaml
+```
 
-## Deployment
+In the near future there will be better integration of this way of handling
+sensitive configuration data with Flux.
 
-Next deploy the secrets - see the *secrets* section above.
+## Deployment
 
-Finally deploy Flux and point it to this repository (the git.url value below):
+You need to deploy both the helm operator and flux itself:
 ```bash
-$ cat flux-values.yaml
-git:
-  path: releases,namespaces
-  pollInterval: 1m
-  readonly: true
-rbac:
-  create: true
-
-$ helm install fluxcd/flux --namespace flux --name flux --values flux-values.yaml \
-    --set git.url=https://gitlab.cern.ch/helm/releases/gitops-getting-started
-
-$ cat helm-operator-values.yaml
-createCRD: true
-chartsSyncInterval: 1m
-configureRepositories:
-  enable: true
-  repositories:
-  - name: cern 
-    url: https://registry.cern.ch/cern/charts
-rbac:
-  create: true
-git:
-  pollInterval: 1m
-
-$ helm install fluxcd/helm-operator --namespace flux --name helm-operator --values helm-operator-values.yaml
+$ helm install fluxcd/helm-operator --namespace flux --name helm-operator
+  \ --version 0.4.0 --values helm-operator-values.yaml
+
+$ helm install fluxcd/flux --namespace flux --name flux --version 1.0.0 \
+  --values flux-values.yaml \
+  --set git.url=https://gitlab.cern.ch/helm/releases/gitops-getting-started
 ```
 
+The files *helm-operator-values.yaml* and *flux-values.yaml* contain the
+configuration for each of the component. You can change these as you want.
+
 Check the logs to see the multiple releases are being picked up:
 ```
-$ kubectl -n flux logs -f deployment.apps/flux-helm-operator
+$ kubectl -n flux logs -f deployment.apps/helm-operator
+$ kubectl -n flux logs -f deployment.apps/flux
 ```
 
 All going well you should see them in helm:
 ```bash
 $ helm ls
-NAME    REVISION    UPDATED                     STATUS      CHART       APP VERSION NAMESPACE
+NAME                        REVISION    UPDATED                     STATUS      CHART                           APP VERSION NAMESPACE
+flux                        1           Mon Jan 20 23:04:34 2020    DEPLOYED    flux-1.0.0                      1.17.0      flux     
+gitops-getting-started      1           Mon Jan 20 23:17:48 2020    DEPLOYED    gitops-getting-started-0.1.0                prod     
+gitops-getting-started-stg  1           Mon Jan 20 23:17:48 2020    DEPLOYED    gitops-getting-started-0.1.0                stg      
+helm-operator               1           Mon Jan 20 23:04:32 2020    DEPLOYED    helm-operator-0.4.0             1.0.0-rc5   flux  
 ```
 
 ## FAQ
diff --git a/charts/gitops-getting-started/Chart.yaml b/charts/gitops-getting-started/Chart.yaml
new file mode 100644
index 0000000..ecafbdb
--- /dev/null
+++ b/charts/gitops-getting-started/Chart.yaml
@@ -0,0 +1,4 @@
+apiVersion: v1
+description: A Helm chart for a sample gitops application
+name: gitops-getting-started
+version: 0.1.0
diff --git a/charts/gitops-getting-started/requirements.yaml b/charts/gitops-getting-started/requirements.yaml
new file mode 100644
index 0000000..2a7b6fa
--- /dev/null
+++ b/charts/gitops-getting-started/requirements.yaml
@@ -0,0 +1,4 @@
+dependencies:
+  - name: wordpress
+    version: 8.1.1
+    repository: https://kubernetes-charts.storage.googleapis.com
diff --git a/charts/gitops-getting-started/templates/psp.yaml b/charts/gitops-getting-started/templates/psp.yaml
new file mode 100644
index 0000000..f869a1b
--- /dev/null
+++ b/charts/gitops-getting-started/templates/psp.yaml
@@ -0,0 +1,91 @@
+apiVersion: policy/v1beta1
+kind: PodSecurityPolicy
+metadata:
+  name: {{ .Release.Name }}.restricted
+spec:
+  privileged: false
+  # Required to prevent escalations to root.
+  allowPrivilegeEscalation: false
+  # This is redundant with non-root + disallow privilege escalation,
+  # but we can provide it for defense in depth.
+  requiredDropCapabilities:
+    - ALL
+  # Allow core volume types.
+  volumes:
+    - 'hostPath'
+    - 'configMap'
+    - 'emptyDir'
+    - 'secret'
+    - 'persistentVolumeClaim'
+  allowedHostPaths:
+    - pathPrefix: "/var/eos"
+      readOnly: true 
+    - pathPrefix: "/opt/nvidia-driver"
+      readOnly: true
+  hostNetwork: false
+  hostIPC: false
+  hostPID: false
+  runAsUser:
+    # Require the container to run without root privileges.
+    rule: 'MustRunAsNonRoot'
+  seLinux:
+    # This policy assumes the nodes are using AppArmor rather than SELinux.
+    rule: 'RunAsAny'
+  supplementalGroups:
+    rule: 'MustRunAs'
+    ranges:
+      # Forbid adding the root group.
+      - min: 1
+        max: 65535
+  fsGroup:
+    rule: 'MustRunAs'
+    ranges:
+      # Forbid adding the root group.
+      - min: 1
+        max: 65535
+  readOnlyRootFilesystem: false
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  name: {{ .Release.Name }}.psp.restricted
+rules:
+- apiGroups: ['extensions']
+  resources: ['podsecuritypolicies']
+  verbs: ['use']
+  resourceNames: ['{{ .Release.Name }}.restricted']
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+  name: {{ .Release.Name }}.psp.restricted
+roleRef:
+  kind: ClusterRole
+  name: {{ .Release.Name }}.psp.restricted
+  apiGroup: rbac.authorization.k8s.io
+subjects:
+- kind: Group
+  name: system:authenticated
+  apiGroup: rbac.authorization.k8s.io
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+  name: {{ .Release.Name }}.psp.restricted
+rules:
+- apiGroups: ['extensions']
+  resources: ['podsecuritypolicies']
+  verbs: ['use']
+  resourceNames: ['{{ .Release.Name}}.restricted']
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+  name: {{ .Release.Name }}.psp.restricted
+roleRef:
+  kind: Role
+  name: {{ .Release.Name }}.psp.restricted
+  apiGroup: rbac.authorization.k8s.io
+subjects:
+- kind: ServiceAccount
+  name: default
diff --git a/charts/gitops-getting-started/values.yaml b/charts/gitops-getting-started/values.yaml
new file mode 100644
index 0000000..77936f2
--- /dev/null
+++ b/charts/gitops-getting-started/values.yaml
@@ -0,0 +1,21 @@
+
+wordpress:
+  image:
+    registry: "docker.io"
+    repository: "bitnami/wordpress"
+  persistence:
+    enabled: false
+  service:
+    type: "NodePort"
+
+  mariadb:
+    enabled: true
+    image:
+      registry: "docker.io"
+      repository: "bitnami/mariadb"
+    db:
+      name: "wordpress"
+      user: "wordpress"
+    master:
+      persistence:
+        enabled: false
diff --git a/flux-values.yaml b/flux-values.yaml
new file mode 100644
index 0000000..49901bb
--- /dev/null
+++ b/flux-values.yaml
@@ -0,0 +1,6 @@
+git:
+  path: releases,namespaces
+  pollInterval: 5m
+  readonly: true
+rbac:
+  create: true
diff --git a/helm-operator-values.yaml b/helm-operator-values.yaml
new file mode 100644
index 0000000..d41472e
--- /dev/null
+++ b/helm-operator-values.yaml
@@ -0,0 +1,13 @@
+createCRD: true
+chartsSyncInterval: 1m
+configureRepositories:
+  enable: true
+  repositories:
+  - name: stable
+    url: https://kubernetes-charts.storage.googleapis.com
+  - name: cern
+    url: https://registry.cern.ch/chartrepo/cern
+rbac:
+  create: true
+git:
+  pollInterval: 5m
diff --git a/namespaces/prod.yaml b/namespaces/prod.yaml
new file mode 100644
index 0000000..6b93218
--- /dev/null
+++ b/namespaces/prod.yaml
@@ -0,0 +1,5 @@
+---
+apiVersion: v1
+kind: Namespace
+metadata:
+  name: prod
diff --git a/namespaces/stg.yaml b/namespaces/stg.yaml
new file mode 100644
index 0000000..e43e6cc
--- /dev/null
+++ b/namespaces/stg.yaml
@@ -0,0 +1,5 @@
+---
+apiVersion: v1
+kind: Namespace
+metadata:
+  name: stg
diff --git a/releases/prod/values.yaml b/releases/prod/values.yaml
new file mode 100644
index 0000000..2a41551
--- /dev/null
+++ b/releases/prod/values.yaml
@@ -0,0 +1,27 @@
+---
+apiVersion: helm.fluxcd.io/v1
+kind: HelmRelease
+metadata:
+  name: gitops-getting-started
+  namespace: prod
+  annotations:
+    flux.weave.works/automated: "false"
+spec:
+  releaseName: gitops-getting-started
+  chart:
+    git: https://gitlab.cern.ch/helm/releases/gitops-getting-started.git
+    path: charts/gitops-getting-started
+    ref: master
+  valuesFrom:
+  - secretKeyRef:
+      namespace: prod
+      name: gitops-getting-started-secrets
+      key: values.yaml
+  values:
+    wordpress:
+      service:
+        nodePorts:
+          http: "32700"
+      mariadb:
+        image:
+          tag: "10.3.21"
diff --git a/releases/stg/values.yaml b/releases/stg/values.yaml
new file mode 100644
index 0000000..bf5245d
--- /dev/null
+++ b/releases/stg/values.yaml
@@ -0,0 +1,27 @@
+---
+apiVersion: helm.fluxcd.io/v1
+kind: HelmRelease
+metadata:
+  name: gitops-getting-started-stg
+  namespace: stg
+  annotations:
+    flux.weave.works/automated: "false"
+spec:
+  releaseName: gitops-getting-started-stg
+  chart:
+    git: https://gitlab.cern.ch/helm/releases/gitops-getting-started.git
+    path: charts/gitops-getting-started
+    ref: master
+  valuesFrom:
+  - secretKeyRef:
+      namespace: stg
+      name: gitops-getting-started-secrets
+      key: values.yaml
+  values:
+    wordpress:
+      service:
+        nodePorts:
+          http: "32701"
+      mariadb:
+        image:
+          tag: "10.4.11"
diff --git a/secrets/prod/secrets.yaml b/secrets/prod/secrets.yaml
new file mode 100644
index 0000000..99c363e
--- /dev/null
+++ b/secrets/prod/secrets.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: Secret
+metadata:
+  name: gitops-getting-started-secrets
+  namespace: prod
+type: Opaque
+stringData:
+  values.yaml: |-
+    wordpress:
+      mariadb:
+        rootUser:
+          password: "rootsecret"
+        db:
+          password: "supersecret"
diff --git a/secrets/stg/secrets.yaml b/secrets/stg/secrets.yaml
new file mode 100644
index 0000000..debeaca
--- /dev/null
+++ b/secrets/stg/secrets.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: Secret
+metadata:
+  name: gitops-getting-started-secrets
+  namespace: stg
+type: Opaque
+stringData:
+  values.yaml: |-
+    wordpress:
+      mariadb:
+        rootUser:
+          password: "rootsecret"
+        db:
+          password: "supersecret"
-- 
GitLab