diff --git a/template/stacks/core/argocd.yaml b/template/stacks/core/argocd.yaml index 4433721..4f65e09 100644 --- a/template/stacks/core/argocd.yaml +++ b/template/stacks/core/argocd.yaml @@ -21,7 +21,7 @@ spec: # TODO: RIRE Can be updated when https://github.com/argoproj/argo-cd/issues/20790 is fixed and merged # As logout make problems, it is suggested to switch from path based routing to an own argocd domain, # similar to the CNOE amazon reference implementation and in our case, Forgejo - targetRevision: argo-cd-7.6.12 + targetRevision: argo-cd-7.7.5 helm: valueFiles: - $values/stacks/core/argocd/values.yaml diff --git a/template/stacks/monitoring/alloy.yaml b/template/stacks/monitoring/alloy.yaml new file mode 100644 index 0000000..7d4d614 --- /dev/null +++ b/template/stacks/monitoring/alloy.yaml @@ -0,0 +1,29 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: alloy + namespace: argocd + labels: + env: dev + finalizers: + - resources-finalizer.argocd.argoproj.io +spec: + project: default + syncPolicy: + automated: + selfHeal: true + syncOptions: + - CreateNamespace=true + destination: + name: in-cluster + namespace: monitoring + sources: + - repoURL: https://github.com/grafana/alloy.git + path: operations/helm/charts/alloy + targetRevision: HEAD + helm: + valueFiles: + - $values/stacks/monitoring/alloy/values.yaml + - repoURL: https://{{{ .Env.DOMAIN_GITEA }}}/giteaAdmin/edfbuilder + targetRevision: HEAD + ref: values \ No newline at end of file diff --git a/template/stacks/monitoring/alloy/values.yaml b/template/stacks/monitoring/alloy/values.yaml new file mode 100644 index 0000000..3f038fa --- /dev/null +++ b/template/stacks/monitoring/alloy/values.yaml @@ -0,0 +1,4 @@ +alloy: + create: false + name: alloy-config + key: config.alloy diff --git a/template/stacks/monitoring/kube-prometheus-sso.yaml b/template/stacks/monitoring/kube-prometheus-sso.yaml new file mode 100644 index 0000000..0e6e43a --- /dev/null +++ b/template/stacks/monitoring/kube-prometheus-sso.yaml @@ -0,0 +1,29 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: kube-prometheus-sso + namespace: argocd + labels: + env: dev + finalizers: + - resources-finalizer.argocd.argoproj.io +spec: + project: default + source: + repoURL: https://{{{ .Env.DOMAIN_GITEA }}}/giteaAdmin/edfbuilder + targetRevision: HEAD + path: "stacks/monitoring/kube-prometheus-sso" + destination: + server: "https://kubernetes.default.svc" + namespace: monitoring + syncPolicy: + syncOptions: + - CreateNamespace=true + automated: + selfHeal: true + retry: + limit: -1 + backoff: + duration: 15s + factor: 1 + maxDuration: 15s diff --git a/template/stacks/monitoring/kube-prometheus-sso/secret-grafana.yaml b/template/stacks/monitoring/kube-prometheus-sso/secret-grafana.yaml new file mode 100644 index 0000000..896ec1b --- /dev/null +++ b/template/stacks/monitoring/kube-prometheus-sso/secret-grafana.yaml @@ -0,0 +1,21 @@ +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: auth-generic-oauth-secret + namespace: monitoring +spec: + secretStoreRef: + name: keycloak + kind: ClusterSecretStore + refreshInterval: "0" + target: + name: auth-generic-oauth-secret + template: + engineVersion: v2 + data: + client_secret: "{{.GRAFANA_CLIENT_SECRET}}" + data: + - secretKey: GRAFANA_CLIENT_SECRET + remoteRef: + key: keycloak-clients + property: GRAFANA_CLIENT_SECRET diff --git a/template/stacks/monitoring/kube-prometheus.yaml b/template/stacks/monitoring/kube-prometheus.yaml index 32cdc88..7bcf3ca 100644 --- a/template/stacks/monitoring/kube-prometheus.yaml +++ b/template/stacks/monitoring/kube-prometheus.yaml @@ -15,6 +15,12 @@ spec: syncOptions: - CreateNamespace=true - ServerSideApply=true # do not copy metdata, since (because of its large size) it can lead to sync failure + retry: + limit: -1 + backoff: + duration: 15s + factor: 1 + maxDuration: 15s destination: name: in-cluster namespace: monitoring diff --git a/template/stacks/monitoring/kube-prometheus/values.yaml b/template/stacks/monitoring/kube-prometheus/values.yaml index 9c0ca32..901345f 100644 --- a/template/stacks/monitoring/kube-prometheus/values.yaml +++ b/template/stacks/monitoring/kube-prometheus/values.yaml @@ -33,7 +33,33 @@ grafana: domain: {{{ .Env.DOMAIN }}} root_url: "%(protocol)s://%(domain)s/grafana" serve_from_sub_path: true + auth: + disable_login: true + disable_login_form: true + auth.generic_oauth: + enabled: true + name: Keycloak-OAuth + allow_sign_up: true + use_refresh_token: true + client_id: grafana + client_secret: $__file{/etc/secrets/auth_generic_oauth/client_secret} + scopes: openid email profile offline_access roles + email_attribute_path: email + login_attribute_path: username + name_attribute_path: full_name + auth_url: https://{{{ .Env.DOMAIN }}}/keycloak/realms/cnoe/protocol/openid-connect/auth + token_url: https://{{{ .Env.DOMAIN }}}/keycloak/realms/cnoe/protocol/openid-connect/token + api_url: https://{{{ .Env.DOMAIN }}}/keycloak/realms/cnoe/protocol/openid-connect/userinfo + redirect_uri: http://{{{ .Env.DOMAIN }}}/grafana/login/generic_oauth + role_attribute_path: "contains(groups[*], 'admin') && 'Admin' || contains(groups[*], 'editor') && 'Editor' || 'Viewer'" + extraSecretMounts: + - name: auth-generic-oauth-secret-mount + secretName: auth-generic-oauth-secret + defaultMode: 0440 + mountPath: /etc/secrets/auth_generic_oauth + readOnly: true + serviceMonitor: # If true, a ServiceMonitor CRD is created for a prometheus operator https://github.com/coreos/prometheus-operator enabled: true diff --git a/template/stacks/ref-implementation/argo-workflows.yaml b/template/stacks/ref-implementation/argo-workflows.yaml index 3d33891..ef23482 100644 --- a/template/stacks/ref-implementation/argo-workflows.yaml +++ b/template/stacks/ref-implementation/argo-workflows.yaml @@ -23,3 +23,7 @@ spec: selfHeal: true retry: limit: -1 + backoff: + duration: 15s + factor: 1 + maxDuration: 15s diff --git a/template/stacks/ref-implementation/backstage-templates/entities/spring-petclinic/skeleton/.github/workflows/maven-build.yml b/template/stacks/ref-implementation/backstage-templates/entities/spring-petclinic/skeleton/.github/workflows/maven-build.yml index c750bd4..62cbd53 100644 --- a/template/stacks/ref-implementation/backstage-templates/entities/spring-petclinic/skeleton/.github/workflows/maven-build.yml +++ b/template/stacks/ref-implementation/backstage-templates/entities/spring-petclinic/skeleton/.github/workflows/maven-build.yml @@ -33,7 +33,7 @@ jobs: #run: ./mvnw spring-boot:build-image # the original image build run: | export CONTAINER_REPO=$(echo {% raw %}${{ env.GITHUB_REPOSITORY }}{% endraw %} | tr '[:upper:]' '[:lower:]') - ./mvnw com.google.cloud.tools:jib-maven-plugin:3.4.4:build -Djib.allowInsecureRegistries=true -Dimage={{{ .Env.DOMAIN_GITEA }}}/${CONTAINER_REPO}:latest -Djib.to.auth.username={% raw %}${{ github.actor }}{% endraw %} -Djib.to.auth.password={% raw %}${{ secrets.PACKAGES_TOKEN }}{% endraw %} + ./mvnw com.google.cloud.tools:jib-maven-plugin:3.4.4:build -Djib.allowInsecureRegistries=true -Dimage={{{ .Env.DOMAIN_GITEA }}}/${CONTAINER_REPO}:latest -Djib.to.auth.username={% raw %}${{ github.actor }}{% endraw %} -Djib.to.auth.password={% raw %}${{ secrets.PACKAGES_TOKEN }}{% endraw %} -Djib.from.platforms=linux/arm64,linux/amd64 - name: Build image as tar run: | ./mvnw com.google.cloud.tools:jib-maven-plugin:3.4.4:buildTar -Djib.allowInsecureRegistries=true @@ -57,7 +57,11 @@ jobs: NODE_TLS_REJECT_UNAUTHORIZED: 0 # This is necessary due to self signed certs for forgejo, proper setups can skip this - name: install trivy from deb package run: | - wget -O trivy.deb https://github.com/aquasecurity/trivy/releases/download/v0.58.0/trivy_0.58.0_Linux-64bit.deb + if [[ "$(uname -m)" == "x86_64" ]]; then + wget -O trivy.deb https://github.com/aquasecurity/trivy/releases/download/v0.58.0/trivy_0.58.0_Linux-64bit.deb + else + wget -O trivy.deb https://github.com/aquasecurity/trivy/releases/download/v0.58.0/trivy_0.58.0_Linux-ARM64.deb + fi DEBIAN_FRONTEND=noninteractive dpkg -i trivy.deb - name: scan the image run: trivy image --input jib-image.tar diff --git a/template/stacks/ref-implementation/backstage.yaml b/template/stacks/ref-implementation/backstage.yaml index 227d29f..01932dc 100644 --- a/template/stacks/ref-implementation/backstage.yaml +++ b/template/stacks/ref-implementation/backstage.yaml @@ -23,3 +23,7 @@ spec: selfHeal: true retry: limit: -1 + backoff: + duration: 15s + factor: 1 + maxDuration: 15s diff --git a/template/stacks/ref-implementation/keycloak/manifests/keycloak-config.yaml b/template/stacks/ref-implementation/keycloak/manifests/keycloak-config.yaml index e2a0981..6c8d603 100644 --- a/template/stacks/ref-implementation/keycloak/manifests/keycloak-config.yaml +++ b/template/stacks/ref-implementation/keycloak/manifests/keycloak-config.yaml @@ -100,11 +100,11 @@ data: user-user1.json: | { "username": "user1", - "email": "", + "email": "user1@user.de", "firstName": "user", "lastName": "one", "requiredActions": [], - "emailVerified": false, + "emailVerified": true, "groups": [ "/admin" ], @@ -113,11 +113,11 @@ data: user-user2.json: | { "username": "user2", - "email": "", + "email": "user2@user.de", "firstName": "user", "lastName": "two", "requiredActions": [], - "emailVerified": false, + "emailVerified": true, "groups": [ "/base-user" ], @@ -181,6 +181,44 @@ data: ] } + grafana-client-payload.json: | + { + "clientId": "grafana", + "name": "Grafana Client", + "description": "Used for Grafana SSO", + "rootUrl": "https://{{{ .Env.DOMAIN }}}/grafana", + "adminUrl": "https://{{{ .Env.DOMAIN }}}/grafana", + "baseUrl": "https://{{{ .Env.DOMAIN }}}/grafana", + "alwaysDisplayInConsole": false, + "redirectUris": [ + "http://{{{ .Env.DOMAIN }}}/grafana/*" + ], + "webOrigins": [ + "https://{{{ .Env.DOMAIN }}}/grafana" + ], + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": true, + "protocol": "openid-connect", + "attributes": { + "saml_idp_initiated_sso_url_name": "", + "oidc.ciba.grant.enabled": "false", + "oauth2.device.authorization.grant.enabled": "false" + }, + "defaultClientScopes": [ + "web-origins", + "acr", + "offline_access", + "roles", + "profile", + "groups", + "email" + ] + } + --- apiVersion: batch/v1 kind: Job @@ -247,7 +285,11 @@ spec: fi set -e - curl -sS -LO "https://dl.k8s.io/release/v1.28.3//bin/linux/amd64/kubectl" + if [[ "$(uname -m)" == "x86_64" ]]; then + curl -sS -LO "https://dl.k8s.io/release/v1.28.3//bin/linux/amd64/kubectl" + else + curl -sS -LO "https://dl.k8s.io/release/v1.28.3//bin/linux/arm64/kubectl" + fi chmod +x kubectl echo "creating cnoe realm and groups" @@ -330,7 +372,24 @@ spec: ARGO_WORKFLOWS_CLIENT_SECRET=$(curl -sS -H "Content-Type: application/json" \ -H "Authorization: bearer ${KEYCLOAK_TOKEN}" \ -X GET ${KEYCLOAK_URL}/admin/realms/cnoe/clients/${CLIENT_ID} | jq -e -r '.secret') + + echo "creating Grafana client" + curl -sS -H "Content-Type: application/json" \ + -H "Authorization: bearer ${KEYCLOAK_TOKEN}" \ + -X POST --data @/var/config/grafana-client-payload.json \ + ${KEYCLOAK_URL}/admin/realms/cnoe/clients + CLIENT_ID=$(curl -sS -H "Content-Type: application/json" \ + -H "Authorization: bearer ${KEYCLOAK_TOKEN}" \ + -X GET ${KEYCLOAK_URL}/admin/realms/cnoe/clients | jq -e -r '.[] | select(.clientId == "grafana") | .id') + + CLIENT_SCOPE_GROUPS_ID=$(curl -sS -H "Content-Type: application/json" -H "Authorization: bearer ${KEYCLOAK_TOKEN}" -X GET ${KEYCLOAK_URL}/admin/realms/cnoe/client-scopes | jq -e -r '.[] | select(.name == "groups") | .id') + curl -sS -H "Content-Type: application/json" -H "Authorization: bearer ${KEYCLOAK_TOKEN}" -X PUT ${KEYCLOAK_URL}/admin/realms/cnoe/clients/${CLIENT_ID}/default-client-scopes/${CLIENT_SCOPE_GROUPS_ID} + + GRAFANA_CLIENT_SECRET=$(curl -sS -H "Content-Type: application/json" \ + -H "Authorization: bearer ${KEYCLOAK_TOKEN}" \ + -X GET ${KEYCLOAK_URL}/admin/realms/cnoe/clients/${CLIENT_ID} | jq -e -r '.secret') + echo "creating Backstage client" curl -sS -H "Content-Type: application/json" \ -H "Authorization: bearer ${KEYCLOAK_TOKEN}" \ @@ -365,6 +424,8 @@ spec: ARGOCD_SESSION_TOKEN: ${ARGOCD_SESSION_TOKEN} BACKSTAGE_CLIENT_SECRET: ${BACKSTAGE_CLIENT_SECRET} BACKSTAGE_CLIENT_ID: backstage + GRAFANA_CLIENT_SECRET: ${GRAFANA_CLIENT_SECRET} + GRAFANA_CLIENT_ID: grafana " > /tmp/secret.yaml ./kubectl apply -f /tmp/secret.yaml