diff --git a/.gitignore b/.gitignore index 6cd3154..65410ec 100644 --- a/.gitignore +++ b/.gitignore @@ -226,7 +226,6 @@ ClientBin/ *.dbmdl *.dbproj.schemaview *.jfm -*.pfx *.publishsettings orleans.codegen.cs diff --git a/etc/dev-cert/localhost.pfx b/etc/dev-cert/localhost.pfx new file mode 100644 index 0000000..abc91fe Binary files /dev/null and b/etc/dev-cert/localhost.pfx differ diff --git a/etc/k8s/README.md b/etc/k8s/README.md new file mode 100644 index 0000000..7810dae --- /dev/null +++ b/etc/k8s/README.md @@ -0,0 +1,21 @@ + ### Pre-requirements + +* Docker Desktop with Kubernetes enabled +* Install [NGINX ingress](https://kubernetes.github.io/ingress-nginx/deploy/) for k8s + +### How to run? + +* Add entries to the hosts file (in Windows: `C:\Windows\System32\drivers\etc\hosts`): + +```` +127.0.0.1 eh-st-account +127.0.0.1 eh-st-www +127.0.0.1 eh-st-api +127.0.0.1 eh-st-admin +127.0.0.1 eh-st-admin-api +```` + +* Run `build-images.ps1` in the `scripts` directory. +* Run `helm install eh-st eventhub` in the `helm-chart` directory. +* Browse https://eh-st-www and https://eh-st-admin +* Username: `admin`, password: `1q2w3E*`. diff --git a/etc/k8s/helm-chart/deploy-azure.ps1 b/etc/k8s/helm-chart/deploy-azure.ps1 new file mode 100644 index 0000000..96bc82d --- /dev/null +++ b/etc/k8s/helm-chart/deploy-azure.ps1 @@ -0,0 +1 @@ +helm upgrade --install eh-az eventhub -f .\eventhub\values.azure.yaml --namespace eventhub --create-namespace \ No newline at end of file diff --git a/etc/k8s/helm-chart/eventhub/Chart.yaml b/etc/k8s/helm-chart/eventhub/Chart.yaml new file mode 100644 index 0000000..ba07319 --- /dev/null +++ b/etc/k8s/helm-chart/eventhub/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: eventhub +appVersion: "1.0" +description: EventHub solution +version: 1.0.0 +type: application diff --git a/etc/k8s/helm-chart/eventhub/charts/account/Chart.yaml b/etc/k8s/helm-chart/eventhub/charts/account/Chart.yaml new file mode 100644 index 0000000..ad4fd58 --- /dev/null +++ b/etc/k8s/helm-chart/eventhub/charts/account/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: account +appVersion: "1.0" +description: EventHub Account Application +version: 1.0.0 +type: application \ No newline at end of file diff --git a/etc/k8s/helm-chart/eventhub/charts/account/templates/account-ingress.yaml b/etc/k8s/helm-chart/eventhub/charts/account/templates/account-ingress.yaml new file mode 100644 index 0000000..bc7a7b7 --- /dev/null +++ b/etc/k8s/helm-chart/eventhub/charts/account/templates/account-ingress.yaml @@ -0,0 +1,28 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ .Release.Name }}-{{ .Chart.Name }}-ingress + annotations: + nginx.ingress.kubernetes.io/rewrite-target: / + nginx.ingress.kubernetes.io/force-ssl-redirect: "true" + nginx.ingress.kubernetes.io/proxy-buffer-size: "{{ .Values.global.nginxProxyBufferSize }}" + nginx.ingress.kubernetes.io/proxy-buffers-number: "{{ .Values.global.nginxProxyBuffersNumber }}" + cert-manager.io/cluster-issuer: letsencrypt + nginx.ingress.kubernetes.io/configuration-snippet: | + more_set_input_headers "from-ingress: true"; +spec: + tls: + - hosts: + - {{ .Values.global.accountDomain }} + secretName: {{ .Release.Name }}-{{ .Chart.Name }}-tls + rules: + - host: "{{ .Values.global.accountDomain }}" + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: {{ .Release.Name }}-{{ .Chart.Name }} + port: + number: 80 \ No newline at end of file diff --git a/etc/k8s/helm-chart/eventhub/charts/account/templates/account-service.yaml b/etc/k8s/helm-chart/eventhub/charts/account/templates/account-service.yaml new file mode 100644 index 0000000..ee157c0 --- /dev/null +++ b/etc/k8s/helm-chart/eventhub/charts/account/templates/account-service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + name: {{ .Release.Name }}-{{ .Chart.Name }} + name: {{ .Release.Name }}-{{ .Chart.Name }} +spec: + ports: + - name: "80" + port: 80 + - name: "443" + port: 443 + selector: + app: {{ .Release.Name }}-{{ .Chart.Name }} diff --git a/etc/k8s/helm-chart/eventhub/charts/account/templates/account.yaml b/etc/k8s/helm-chart/eventhub/charts/account/templates/account.yaml new file mode 100644 index 0000000..0fc80aa --- /dev/null +++ b/etc/k8s/helm-chart/eventhub/charts/account/templates/account.yaml @@ -0,0 +1,27 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }}-{{ .Chart.Name }} +spec: + selector: + matchLabels: + app: {{ .Release.Name }}-{{ .Chart.Name }} + template: + metadata: + labels: + app: {{ .Release.Name }}-{{ .Chart.Name }} + spec: + containers: + - image: {{ .Values.containerImage }} + imagePullPolicy: {{ .Values.global.imagePullPolicy }} + name: {{ .Release.Name }}-{{ .Chart.Name }} + ports: + - name: http + containerPort: 80 + - name: https + containerPort: 443 + env: +{{ include "eventhub.global.env" . | indent 8 }} + - name: "ConnectionStrings__Default" + value: {{ .Values.global.defaultConnString }} + diff --git a/etc/k8s/helm-chart/eventhub/charts/account/values.yaml b/etc/k8s/helm-chart/eventhub/charts/account/values.yaml new file mode 100644 index 0000000..e69de29 diff --git a/etc/k8s/helm-chart/eventhub/charts/admin-api/Chart.yaml b/etc/k8s/helm-chart/eventhub/charts/admin-api/Chart.yaml new file mode 100644 index 0000000..4b82d4b --- /dev/null +++ b/etc/k8s/helm-chart/eventhub/charts/admin-api/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: admin-api +appVersion: "1.0" +description: EventHub Admin API Application +version: 1.0.0 +type: application \ No newline at end of file diff --git a/etc/k8s/helm-chart/eventhub/charts/admin-api/templates/admin-api-ingress.yaml b/etc/k8s/helm-chart/eventhub/charts/admin-api/templates/admin-api-ingress.yaml new file mode 100644 index 0000000..e59ac77 --- /dev/null +++ b/etc/k8s/helm-chart/eventhub/charts/admin-api/templates/admin-api-ingress.yaml @@ -0,0 +1,26 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ .Release.Name }}-{{ .Chart.Name }}-ingress + annotations: + nginx.ingress.kubernetes.io/rewrite-target: / + nginx.ingress.kubernetes.io/force-ssl-redirect: "true" + nginx.ingress.kubernetes.io/proxy-buffer-size: "{{ .Values.global.nginxProxyBufferSize }}" + nginx.ingress.kubernetes.io/proxy-buffers-number: "{{ .Values.global.nginxProxyBuffersNumber }}" + cert-manager.io/cluster-issuer: letsencrypt +spec: + tls: + - hosts: + - {{ .Values.global.adminApiDomain }} + secretName: {{ .Release.Name }}-{{ .Chart.Name }}-tls + rules: + - host: "{{ .Values.global.adminApiDomain }}" + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: {{ .Release.Name }}-{{ .Chart.Name }} + port: + number: 80 \ No newline at end of file diff --git a/etc/k8s/helm-chart/eventhub/charts/admin-api/templates/admin-api-service.yaml b/etc/k8s/helm-chart/eventhub/charts/admin-api/templates/admin-api-service.yaml new file mode 100644 index 0000000..ee157c0 --- /dev/null +++ b/etc/k8s/helm-chart/eventhub/charts/admin-api/templates/admin-api-service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + name: {{ .Release.Name }}-{{ .Chart.Name }} + name: {{ .Release.Name }}-{{ .Chart.Name }} +spec: + ports: + - name: "80" + port: 80 + - name: "443" + port: 443 + selector: + app: {{ .Release.Name }}-{{ .Chart.Name }} diff --git a/etc/k8s/helm-chart/eventhub/charts/admin-api/templates/admin-api.yaml b/etc/k8s/helm-chart/eventhub/charts/admin-api/templates/admin-api.yaml new file mode 100644 index 0000000..0fc80aa --- /dev/null +++ b/etc/k8s/helm-chart/eventhub/charts/admin-api/templates/admin-api.yaml @@ -0,0 +1,27 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }}-{{ .Chart.Name }} +spec: + selector: + matchLabels: + app: {{ .Release.Name }}-{{ .Chart.Name }} + template: + metadata: + labels: + app: {{ .Release.Name }}-{{ .Chart.Name }} + spec: + containers: + - image: {{ .Values.containerImage }} + imagePullPolicy: {{ .Values.global.imagePullPolicy }} + name: {{ .Release.Name }}-{{ .Chart.Name }} + ports: + - name: http + containerPort: 80 + - name: https + containerPort: 443 + env: +{{ include "eventhub.global.env" . | indent 8 }} + - name: "ConnectionStrings__Default" + value: {{ .Values.global.defaultConnString }} + diff --git a/etc/k8s/helm-chart/eventhub/charts/admin-api/values.yaml b/etc/k8s/helm-chart/eventhub/charts/admin-api/values.yaml new file mode 100644 index 0000000..e69de29 diff --git a/etc/k8s/helm-chart/eventhub/charts/admin/Chart.yaml b/etc/k8s/helm-chart/eventhub/charts/admin/Chart.yaml new file mode 100644 index 0000000..6432aff --- /dev/null +++ b/etc/k8s/helm-chart/eventhub/charts/admin/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: admin +appVersion: "1.0" +description: EventHub Admin Application +version: 1.0.0 +type: application \ No newline at end of file diff --git a/etc/k8s/helm-chart/eventhub/charts/admin/templates/admin-ingress.yaml b/etc/k8s/helm-chart/eventhub/charts/admin/templates/admin-ingress.yaml new file mode 100644 index 0000000..c2d1bc8 --- /dev/null +++ b/etc/k8s/helm-chart/eventhub/charts/admin/templates/admin-ingress.yaml @@ -0,0 +1,28 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ .Release.Name }}-{{ .Chart.Name }}-ingress + annotations: + nginx.ingress.kubernetes.io/rewrite-target: / + nginx.ingress.kubernetes.io/force-ssl-redirect: "true" + nginx.ingress.kubernetes.io/proxy-buffer-size: "{{ .Values.global.nginxProxyBufferSize }}" + nginx.ingress.kubernetes.io/proxy-buffers-number: "{{ .Values.global.nginxProxyBuffersNumber }}" + cert-manager.io/cluster-issuer: letsencrypt + nginx.ingress.kubernetes.io/configuration-snippet: | + more_set_headers "blazor-environment: {{ .Values.global.dotnetEnvironment }}"; +spec: + tls: + - hosts: + - {{ .Values.global.adminDomain }} + secretName: {{ .Release.Name }}-{{ .Chart.Name }}-tls + rules: + - host: "{{ .Values.global.adminDomain }}" + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: {{ .Release.Name }}-{{ .Chart.Name }} + port: + number: 80 \ No newline at end of file diff --git a/etc/k8s/helm-chart/eventhub/charts/admin/templates/admin-service.yaml b/etc/k8s/helm-chart/eventhub/charts/admin/templates/admin-service.yaml new file mode 100644 index 0000000..ee157c0 --- /dev/null +++ b/etc/k8s/helm-chart/eventhub/charts/admin/templates/admin-service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + name: {{ .Release.Name }}-{{ .Chart.Name }} + name: {{ .Release.Name }}-{{ .Chart.Name }} +spec: + ports: + - name: "80" + port: 80 + - name: "443" + port: 443 + selector: + app: {{ .Release.Name }}-{{ .Chart.Name }} diff --git a/etc/k8s/helm-chart/eventhub/charts/admin/templates/admin.yaml b/etc/k8s/helm-chart/eventhub/charts/admin/templates/admin.yaml new file mode 100644 index 0000000..ca27707 --- /dev/null +++ b/etc/k8s/helm-chart/eventhub/charts/admin/templates/admin.yaml @@ -0,0 +1,24 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }}-{{ .Chart.Name }} +spec: + selector: + matchLabels: + app: {{ .Release.Name }}-{{ .Chart.Name }} + template: + metadata: + labels: + app: {{ .Release.Name }}-{{ .Chart.Name }} + spec: + containers: + - image: {{ .Values.containerImage }} + imagePullPolicy: {{ .Values.global.imagePullPolicy }} + name: {{ .Release.Name }}-{{ .Chart.Name }} + ports: + - name: http + containerPort: 80 + - name: https + containerPort: 443 + env: +{{ include "eventhub.global.env" . | indent 8 }} diff --git a/etc/k8s/helm-chart/eventhub/charts/admin/values.yaml b/etc/k8s/helm-chart/eventhub/charts/admin/values.yaml new file mode 100644 index 0000000..e69de29 diff --git a/etc/k8s/helm-chart/eventhub/charts/api/Chart.yaml b/etc/k8s/helm-chart/eventhub/charts/api/Chart.yaml new file mode 100644 index 0000000..fa75f5b --- /dev/null +++ b/etc/k8s/helm-chart/eventhub/charts/api/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: api +appVersion: "1.0" +description: EventHub API Application +version: 1.0.0 +type: application \ No newline at end of file diff --git a/etc/k8s/helm-chart/eventhub/charts/api/templates/api-ingress.yaml b/etc/k8s/helm-chart/eventhub/charts/api/templates/api-ingress.yaml new file mode 100644 index 0000000..2a678ad --- /dev/null +++ b/etc/k8s/helm-chart/eventhub/charts/api/templates/api-ingress.yaml @@ -0,0 +1,26 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ .Release.Name }}-{{ .Chart.Name }}-ingress + annotations: + nginx.ingress.kubernetes.io/rewrite-target: / + nginx.ingress.kubernetes.io/force-ssl-redirect: "true" + nginx.ingress.kubernetes.io/proxy-buffer-size: "{{ .Values.global.nginxProxyBufferSize }}" + nginx.ingress.kubernetes.io/proxy-buffers-number: "{{ .Values.global.nginxProxyBuffersNumber }}" + cert-manager.io/cluster-issuer: letsencrypt +spec: + tls: + - hosts: + - {{ .Values.global.apiDomain }} + secretName: {{ .Release.Name }}-{{ .Chart.Name }}-tls + rules: + - host: "{{ .Values.global.apiDomain }}" + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: {{ .Release.Name }}-{{ .Chart.Name }} + port: + number: 80 \ No newline at end of file diff --git a/etc/k8s/helm-chart/eventhub/charts/api/templates/api-service.yaml b/etc/k8s/helm-chart/eventhub/charts/api/templates/api-service.yaml new file mode 100644 index 0000000..ee157c0 --- /dev/null +++ b/etc/k8s/helm-chart/eventhub/charts/api/templates/api-service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + name: {{ .Release.Name }}-{{ .Chart.Name }} + name: {{ .Release.Name }}-{{ .Chart.Name }} +spec: + ports: + - name: "80" + port: 80 + - name: "443" + port: 443 + selector: + app: {{ .Release.Name }}-{{ .Chart.Name }} diff --git a/etc/k8s/helm-chart/eventhub/charts/api/templates/api.yaml b/etc/k8s/helm-chart/eventhub/charts/api/templates/api.yaml new file mode 100644 index 0000000..0fc80aa --- /dev/null +++ b/etc/k8s/helm-chart/eventhub/charts/api/templates/api.yaml @@ -0,0 +1,27 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }}-{{ .Chart.Name }} +spec: + selector: + matchLabels: + app: {{ .Release.Name }}-{{ .Chart.Name }} + template: + metadata: + labels: + app: {{ .Release.Name }}-{{ .Chart.Name }} + spec: + containers: + - image: {{ .Values.containerImage }} + imagePullPolicy: {{ .Values.global.imagePullPolicy }} + name: {{ .Release.Name }}-{{ .Chart.Name }} + ports: + - name: http + containerPort: 80 + - name: https + containerPort: 443 + env: +{{ include "eventhub.global.env" . | indent 8 }} + - name: "ConnectionStrings__Default" + value: {{ .Values.global.defaultConnString }} + diff --git a/etc/k8s/helm-chart/eventhub/charts/api/values.yaml b/etc/k8s/helm-chart/eventhub/charts/api/values.yaml new file mode 100644 index 0000000..e69de29 diff --git a/etc/k8s/helm-chart/eventhub/charts/background-services/Chart.yaml b/etc/k8s/helm-chart/eventhub/charts/background-services/Chart.yaml new file mode 100644 index 0000000..ce84bfe --- /dev/null +++ b/etc/k8s/helm-chart/eventhub/charts/background-services/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: background-services +appVersion: "1.0" +description: EventHub Background Services Application +version: 1.0.0 +type: application \ No newline at end of file diff --git a/etc/k8s/helm-chart/eventhub/charts/background-services/templates/background-services.yaml b/etc/k8s/helm-chart/eventhub/charts/background-services/templates/background-services.yaml new file mode 100644 index 0000000..6e7d8ee --- /dev/null +++ b/etc/k8s/helm-chart/eventhub/charts/background-services/templates/background-services.yaml @@ -0,0 +1,18 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ .Release.Name }}-{{ .Chart.Name }} +spec: + activeDeadlineSeconds: 180 + template: + spec: + containers: + - name: {{ .Release.Name }}-{{ .Chart.Name }} + image: {{ .Values.containerImage }} + imagePullPolicy: {{ .Values.global.imagePullPolicy }} + env: +{{ include "eventhub.global.env" . | indent 8 }} + - name: "ConnectionStrings__Default" + value: {{ .Values.global.defaultConnString }} + restartPolicy: Never + backoffLimit: 10 \ No newline at end of file diff --git a/etc/k8s/helm-chart/eventhub/charts/background-services/values.yaml b/etc/k8s/helm-chart/eventhub/charts/background-services/values.yaml new file mode 100644 index 0000000..e69de29 diff --git a/etc/k8s/helm-chart/eventhub/charts/dbmigrator/Chart.yaml b/etc/k8s/helm-chart/eventhub/charts/dbmigrator/Chart.yaml new file mode 100644 index 0000000..fa640cd --- /dev/null +++ b/etc/k8s/helm-chart/eventhub/charts/dbmigrator/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: dbmigrator +appVersion: "1.0" +description: EventHub Migrator Application +version: 1.0.0 +type: application \ No newline at end of file diff --git a/etc/k8s/helm-chart/eventhub/charts/dbmigrator/templates/migrator.yaml b/etc/k8s/helm-chart/eventhub/charts/dbmigrator/templates/migrator.yaml new file mode 100644 index 0000000..03b7b64 --- /dev/null +++ b/etc/k8s/helm-chart/eventhub/charts/dbmigrator/templates/migrator.yaml @@ -0,0 +1,24 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ .Release.Name }}-{{ .Chart.Name }} +spec: + activeDeadlineSeconds: 180 + template: + spec: + containers: + - name: {{ .Release.Name }}-{{ .Chart.Name }} + image: {{ .Values.containerImage }} + imagePullPolicy: {{ .Values.global.imagePullPolicy }} + env: +{{ include "eventhub.global.env" . | indent 8 }} + - name: "ConnectionStrings__Default" + value: {{ .Values.global.defaultConnString }} + - name: "IdentityServer__Clients__EventHub_Web__RootUrl" + value: {{ .Values.global.wwwUrl }} + - name: "IdentityServer__Clients__EventHub_Blazor__RootUrl" + value: {{ .Values.global.adminUrl }} + - name: "IdentityServer__Clients__EventHub_Swagger__RootUrl" + value: {{ .Values.global.apiUrl }} + restartPolicy: Never + backoffLimit: 10 \ No newline at end of file diff --git a/etc/k8s/helm-chart/eventhub/charts/dbmigrator/values.yaml b/etc/k8s/helm-chart/eventhub/charts/dbmigrator/values.yaml new file mode 100644 index 0000000..e69de29 diff --git a/etc/k8s/helm-chart/eventhub/charts/postgresql/Chart.yaml b/etc/k8s/helm-chart/eventhub/charts/postgresql/Chart.yaml new file mode 100644 index 0000000..ce984f6 --- /dev/null +++ b/etc/k8s/helm-chart/eventhub/charts/postgresql/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: postgresql +appVersion: "1.0" +description: Runs PostgreSQL Instance +version: 1.0.0 +type: application diff --git a/etc/k8s/helm-chart/eventhub/charts/postgresql/templates/postgresql-service.yaml b/etc/k8s/helm-chart/eventhub/charts/postgresql/templates/postgresql-service.yaml new file mode 100644 index 0000000..6c08d9d --- /dev/null +++ b/etc/k8s/helm-chart/eventhub/charts/postgresql/templates/postgresql-service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + name: {{ .Release.Name }}-{{ .Chart.Name }} + name: {{ .Release.Name }}-{{ .Chart.Name }} +spec: + type: ClusterIP + ports: + - name: postgresql + port: 5432 + selector: + app: {{ .Release.Name }}-{{ .Chart.Name }} + diff --git a/etc/k8s/helm-chart/eventhub/charts/postgresql/templates/postgresql.yaml b/etc/k8s/helm-chart/eventhub/charts/postgresql/templates/postgresql.yaml new file mode 100644 index 0000000..3d37d3d --- /dev/null +++ b/etc/k8s/helm-chart/eventhub/charts/postgresql/templates/postgresql.yaml @@ -0,0 +1,43 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ .Release.Name }}-{{ .Chart.Name }} +spec: + serviceName: {{ .Release.Name }}-{{ .Chart.Name }} + replicas: 1 + selector: + matchLabels: + app: {{ .Release.Name }}-{{ .Chart.Name }} + template: + metadata: + labels: + app: {{ .Release.Name }}-{{ .Chart.Name }} + spec: + containers: + - image: postgres + name: {{ .Release.Name }}-{{ .Chart.Name }} +{{- if eq .Release.Name "eh-az" }} + volumeMounts: + - mountPath: "/var/lib/postgresql/data" + name: {{ .Release.Name }}-{{ .Chart.Name }}-database-volume + subPath: postgresql-data +{{- end }} + ports: + - name: postgresql + containerPort: 5432 + env: + - name: POSTGRES_USER + value: "root" + - name: POSTGRES_PASSWORD + value: "root" +{{- if eq .Release.Name "eh-az" }} + volumeClaimTemplates: + - metadata: + name: {{ .Release.Name }}-{{ .Chart.Name }}-database-volume + spec: + accessModes: [ "ReadWriteOnce" ] + storageClassName: "managed-premium-retain" + resources: + requests: + storage: 64Gi +{{- end }} \ No newline at end of file diff --git a/etc/k8s/helm-chart/eventhub/charts/postgresql/values.yaml b/etc/k8s/helm-chart/eventhub/charts/postgresql/values.yaml new file mode 100644 index 0000000..e69de29 diff --git a/etc/k8s/helm-chart/eventhub/charts/redis/Chart.yaml b/etc/k8s/helm-chart/eventhub/charts/redis/Chart.yaml new file mode 100644 index 0000000..11ec26c --- /dev/null +++ b/etc/k8s/helm-chart/eventhub/charts/redis/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: redis +appVersion: "1.0" +description: Runs Redis instance +version: 1.0.0 +type: application diff --git a/etc/k8s/helm-chart/eventhub/charts/redis/templates/redis-service.yaml b/etc/k8s/helm-chart/eventhub/charts/redis/templates/redis-service.yaml new file mode 100644 index 0000000..23800f9 --- /dev/null +++ b/etc/k8s/helm-chart/eventhub/charts/redis/templates/redis-service.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + name: {{ .Release.Name }}-{{ .Chart.Name }} + name: {{ .Release.Name }}-{{ .Chart.Name }} +spec: + type: ClusterIP + ports: + - name: redis + port: 6379 + selector: + app: {{ .Release.Name }}-{{ .Chart.Name }} \ No newline at end of file diff --git a/etc/k8s/helm-chart/eventhub/charts/redis/templates/redis.yaml b/etc/k8s/helm-chart/eventhub/charts/redis/templates/redis.yaml new file mode 100644 index 0000000..2ba176d --- /dev/null +++ b/etc/k8s/helm-chart/eventhub/charts/redis/templates/redis.yaml @@ -0,0 +1,20 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }}-{{ .Chart.Name }} +spec: + replicas: 1 + selector: + matchLabels: + app: {{ .Release.Name }}-{{ .Chart.Name }} + template: + metadata: + labels: + app: {{ .Release.Name }}-{{ .Chart.Name }} + spec: + containers: + - image: redis:6.0.10-alpine + name: {{ .Release.Name }}-{{ .Chart.Name }} + ports: + - name: redis + containerPort: 6379 \ No newline at end of file diff --git a/etc/k8s/helm-chart/eventhub/charts/redis/values.yaml b/etc/k8s/helm-chart/eventhub/charts/redis/values.yaml new file mode 100644 index 0000000..e69de29 diff --git a/etc/k8s/helm-chart/eventhub/charts/www/Chart.yaml b/etc/k8s/helm-chart/eventhub/charts/www/Chart.yaml new file mode 100644 index 0000000..319d808 --- /dev/null +++ b/etc/k8s/helm-chart/eventhub/charts/www/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: www +appVersion: "1.0" +description: EventHub WWW Application +version: 1.0.0 +type: application \ No newline at end of file diff --git a/etc/k8s/helm-chart/eventhub/charts/www/templates/www-ingress.yaml b/etc/k8s/helm-chart/eventhub/charts/www/templates/www-ingress.yaml new file mode 100644 index 0000000..1fc3832 --- /dev/null +++ b/etc/k8s/helm-chart/eventhub/charts/www/templates/www-ingress.yaml @@ -0,0 +1,36 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ .Release.Name }}-{{ .Chart.Name }}-ingress + annotations: + nginx.ingress.kubernetes.io/rewrite-target: / + nginx.ingress.kubernetes.io/force-ssl-redirect: "true" + nginx.ingress.kubernetes.io/proxy-buffer-size: "{{ .Values.global.nginxProxyBufferSize }}" + nginx.ingress.kubernetes.io/proxy-buffers-number: "{{ .Values.global.nginxProxyBuffersNumber }}" +{{- if eq .Release.Name "eh-az" }} + nginx.ingress.kubernetes.io/from-to-www-redirect: "true" +{{- end }} + cert-manager.io/cluster-issuer: letsencrypt +spec: + tls: + - hosts: + - {{ .Values.global.wwwDomain }} +{{- if eq .Release.Name "eh-az" }} + - {{ print "www." .Values.global.wwwDomain }} +{{- end }} + secretName: {{ .Release.Name }}-{{ .Chart.Name }}-tls + rules: +{{- if eq .Release.Name "eh-az" }} + - host: "{{ print "www." .Values.global.wwwDomain }}" +{{- else }} + - host: "{{ .Values.global.wwwDomain }}" +{{- end }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: {{ .Release.Name }}-{{ .Chart.Name }} + port: + number: 80 \ No newline at end of file diff --git a/etc/k8s/helm-chart/eventhub/charts/www/templates/www-service.yaml b/etc/k8s/helm-chart/eventhub/charts/www/templates/www-service.yaml new file mode 100644 index 0000000..ee157c0 --- /dev/null +++ b/etc/k8s/helm-chart/eventhub/charts/www/templates/www-service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + name: {{ .Release.Name }}-{{ .Chart.Name }} + name: {{ .Release.Name }}-{{ .Chart.Name }} +spec: + ports: + - name: "80" + port: 80 + - name: "443" + port: 443 + selector: + app: {{ .Release.Name }}-{{ .Chart.Name }} diff --git a/etc/k8s/helm-chart/eventhub/charts/www/templates/www.yaml b/etc/k8s/helm-chart/eventhub/charts/www/templates/www.yaml new file mode 100644 index 0000000..ca27707 --- /dev/null +++ b/etc/k8s/helm-chart/eventhub/charts/www/templates/www.yaml @@ -0,0 +1,24 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }}-{{ .Chart.Name }} +spec: + selector: + matchLabels: + app: {{ .Release.Name }}-{{ .Chart.Name }} + template: + metadata: + labels: + app: {{ .Release.Name }}-{{ .Chart.Name }} + spec: + containers: + - image: {{ .Values.containerImage }} + imagePullPolicy: {{ .Values.global.imagePullPolicy }} + name: {{ .Release.Name }}-{{ .Chart.Name }} + ports: + - name: http + containerPort: 80 + - name: https + containerPort: 443 + env: +{{ include "eventhub.global.env" . | indent 8 }} diff --git a/etc/k8s/helm-chart/eventhub/charts/www/values.yaml b/etc/k8s/helm-chart/eventhub/charts/www/values.yaml new file mode 100644 index 0000000..e69de29 diff --git a/etc/k8s/helm-chart/eventhub/templates/_helpers.tpl b/etc/k8s/helm-chart/eventhub/templates/_helpers.tpl new file mode 100644 index 0000000..cfa6a9c --- /dev/null +++ b/etc/k8s/helm-chart/eventhub/templates/_helpers.tpl @@ -0,0 +1,24 @@ +{{- define "eventhub.global.env" -}} +- name: "DOTNET_ENVIRONMENT" + value: "{{ .Values.global.dotnetEnvironment }}" +- name: "AppUrls__Account" + value: "{{ .Values.global.accountUrl }}" +- name: "AppUrls__Www" + value: "{{ .Values.global.wwwUrl }}" +- name: "AppUrls__Api" + value: "{{ .Values.global.apiUrl }}" +- name: "AppUrls__ApiInternal" + value: "{{ .Values.global.apiUrlInternal }}" +- name: "AppUrls__Admin" + value: "{{ .Values.global.adminUrl }}" +- name: "AppUrls__AdminApi" + value: "{{ .Values.global.adminApiUrl }}" +- name: "Redis__Configuration" + value: "{{ .Values.global.redisConfiguration }}" +- name: "AuthServer__Authority" + value: "{{ .Values.global.internalAuthServerAuthority }}" +- name: "AuthServer__RequireHttpsMetadata" + value: "{{ .Values.global.internalAuthServerRequireHttpsMetadata }}" +- name: "StringEncryption__DefaultPassPhrase" + value: "{{ .Values.global.stringEncryptionDefaultPassPhrase }}" +{{- end }} \ No newline at end of file diff --git a/etc/k8s/helm-chart/eventhub/templates/managed-premium-retain.yaml b/etc/k8s/helm-chart/eventhub/templates/managed-premium-retain.yaml new file mode 100644 index 0000000..3ad6d00 --- /dev/null +++ b/etc/k8s/helm-chart/eventhub/templates/managed-premium-retain.yaml @@ -0,0 +1,11 @@ +{{- if eq .Release.Name "eh-az" }} +kind: StorageClass +apiVersion: storage.k8s.io/v1 +metadata: + name: managed-premium-retain +provisioner: kubernetes.io/azure-disk +reclaimPolicy: Retain +parameters: + storageaccounttype: Premium_LRS + kind: Managed +{{- end }} \ No newline at end of file diff --git a/etc/k8s/helm-chart/eventhub/values.azure.yaml b/etc/k8s/helm-chart/eventhub/values.azure.yaml new file mode 100644 index 0000000..c98ca3c --- /dev/null +++ b/etc/k8s/helm-chart/eventhub/values.azure.yaml @@ -0,0 +1,35 @@ +global: + dotnetEnvironment: 'Production' + accountDomain: account.openeventhub.com + accountUrl: https://account.openeventhub.com + apiDomain: api.openeventhub.com + apiUrl: https://api.openeventhub.com + apiUrlInternal: http://eh-az-api + wwwDomain: openeventhub.com + wwwUrl: "https://www.openeventhub.com" + adminDomain: admin.openeventhub.com + adminUrl: https://admin.openeventhub.com + adminApiDomain: admin-api.openeventhub.com + adminApiUrl: https://admin-api.openeventhub.com + nginxProxyBufferSize: "32k" + nginxProxyBuffersNumber: "8" + defaultConnString: "Host=eh-az-postgresql;Port=5432;Database=EventHub;Username=root;Password=root" + redisConfiguration: "eh-az-redis" + internalAuthServerAuthority: "http://account.openeventhub.com" + internalAuthServerRequireHttpsMetadata: "false" + stringEncryptionDefaultPassPhrase: "TxVIZFPxK33czbbv" + imagePullPolicy: Always +account: + containerImage: "volocr.azurecr.io/eventhub.account" +api: + containerImage: "volocr.azurecr.io/eventhub.api" +www: + containerImage: "volocr.azurecr.io/eventhub.www" +admin-api: + containerImage: "volocr.azurecr.io/eventhub.admin-api" +admin: + containerImage: "volocr.azurecr.io/eventhub.admin" +dbmigrator: + containerImage: "volocr.azurecr.io/eventhub.dbmigrator" +background-services: + containerImage: "volocr.azurecr.io/eventhub.background-services" \ No newline at end of file diff --git a/etc/k8s/helm-chart/eventhub/values.yaml b/etc/k8s/helm-chart/eventhub/values.yaml new file mode 100644 index 0000000..0fd8d6a --- /dev/null +++ b/etc/k8s/helm-chart/eventhub/values.yaml @@ -0,0 +1,35 @@ +global: + dotnetEnvironment: 'Staging' + accountDomain: eh-st-account + accountUrl: https://eh-st-account + apiDomain: eh-st-api + apiUrl: https://eh-st-api + apiUrlInternal: http://eh-st-api + wwwDomain: eh-st-www + wwwUrl: "https://eh-st-www" + adminDomain: eh-st-admin + adminUrl: https://eh-st-admin + adminApiDomain: eh-st-admin-api + adminApiUrl: https://eh-st-admin-api + nginxProxyBufferSize: "32k" + nginxProxyBuffersNumber: "8" + defaultConnString: "Host=eh-st-postgresql;Port=5432;Database=EventHub;Username=root;Password=root" + redisConfiguration: "eh-st-redis" + internalAuthServerAuthority: "http://eh-st-account" + internalAuthServerRequireHttpsMetadata: "false" + stringEncryptionDefaultPassPhrase: "TxVIZFPxK33czbbv" + imagePullPolicy: Never +account: + containerImage: "eventhub.account" +api: + containerImage: "eventhub.api" +www: + containerImage: "eventhub.www" +admin-api: + containerImage: "eventhub.admin-api" +admin: + containerImage: "eventhub.admin" +dbmigrator: + containerImage: "eventhub.dbmigrator" +background-services: + containerImage: "eventhub.background-services" \ No newline at end of file diff --git a/etc/k8s/scripts/azure/cluster-issuer.yaml b/etc/k8s/scripts/azure/cluster-issuer.yaml new file mode 100644 index 0000000..c3445a0 --- /dev/null +++ b/etc/k8s/scripts/azure/cluster-issuer.yaml @@ -0,0 +1,18 @@ +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: letsencrypt +spec: + acme: + server: https://acme-v02.api.letsencrypt.org/directory + email: info@volosoft.com + privateKeySecretRef: + name: letsencrypt + solvers: + - http01: + ingress: + class: nginx + podTemplate: + spec: + nodeSelector: + "kubernetes.io/os": linux \ No newline at end of file diff --git a/etc/k8s/scripts/azure/configure-dns.ps1 b/etc/k8s/scripts/azure/configure-dns.ps1 new file mode 100644 index 0000000..b02d007 --- /dev/null +++ b/etc/k8s/scripts/azure/configure-dns.ps1 @@ -0,0 +1,2 @@ +kubectl apply -f .\corednsms.yaml +kubectl delete pod --namespace kube-system -l k8s-app=kube-dns \ No newline at end of file diff --git a/etc/k8s/scripts/azure/corednsms.yaml b/etc/k8s/scripts/azure/corednsms.yaml new file mode 100644 index 0000000..940e126 --- /dev/null +++ b/etc/k8s/scripts/azure/corednsms.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: coredns-custom + namespace: kube-system +data: + Corefile.override: | + rewrite name substring account.openeventhub.com eh-az-account \ No newline at end of file diff --git a/etc/k8s/scripts/azure/install-ingress.ps1 b/etc/k8s/scripts/azure/install-ingress.ps1 new file mode 100644 index 0000000..153ed91 --- /dev/null +++ b/etc/k8s/scripts/azure/install-ingress.ps1 @@ -0,0 +1,69 @@ +$REGISTRY_NAME="volocr.azurecr.io" +$ACR_URL="volocr.azurecr.io" +$CONTROLLER_REGISTRY="k8s.gcr.io" +$CONTROLLER_IMAGE="ingress-nginx/controller" +$CONTROLLER_TAG="v0.48.1" +$PATCH_REGISTRY="docker.io" +$PATCH_IMAGE="jettech/kube-webhook-certgen" +$PATCH_TAG="v1.5.1" +$DEFAULTBACKEND_REGISTRY="k8s.gcr.io" +$DEFAULTBACKEND_IMAGE="defaultbackend-amd64" +$DEFAULTBACKEND_TAG="1.5" +$CERT_MANAGER_REGISTRY="quay.io" +$CERT_MANAGER_TAG="v1.3.1" +$CERT_MANAGER_IMAGE_CONTROLLER="jetstack/cert-manager-controller" +$CERT_MANAGER_IMAGE_WEBHOOK="jetstack/cert-manager-webhook" +$CERT_MANAGER_IMAGE_CAINJECTOR="jetstack/cert-manager-cainjector" + +az acr import --name $REGISTRY_NAME --source ${CONTROLLER_REGISTRY}/${CONTROLLER_IMAGE}:${CONTROLLER_TAG} --image ${CONTROLLER_IMAGE}:${CONTROLLER_TAG} +az acr import --name $REGISTRY_NAME --source ${PATCH_REGISTRY}/${PATCH_IMAGE}:${PATCH_TAG} --image ${PATCH_IMAGE}:${PATCH_TAG} +az acr import --name $REGISTRY_NAME --source ${DEFAULTBACKEND_REGISTRY}/${DEFAULTBACKEND_IMAGE}:${DEFAULTBACKEND_TAG} --image ${DEFAULTBACKEND_IMAGE}:${DEFAULTBACKEND_TAG} +az acr import --name $REGISTRY_NAME --source ${CERT_MANAGER_REGISTRY}/${CERT_MANAGER_IMAGE_CONTROLLER}:${CERT_MANAGER_TAG} --image ${CERT_MANAGER_IMAGE_CONTROLLER}:${CERT_MANAGER_TAG} +az acr import --name $REGISTRY_NAME --source ${CERT_MANAGER_REGISTRY}/${CERT_MANAGER_IMAGE_WEBHOOK}:${CERT_MANAGER_TAG} --image ${CERT_MANAGER_IMAGE_WEBHOOK}:${CERT_MANAGER_TAG} +az acr import --name $REGISTRY_NAME --source ${CERT_MANAGER_REGISTRY}/${CERT_MANAGER_IMAGE_CAINJECTOR}:${CERT_MANAGER_TAG} --image ${CERT_MANAGER_IMAGE_CAINJECTOR}:${CERT_MANAGER_TAG} + +# Create a namespace for your ingress resources +kubectl create namespace ingress-basic + +# Add the ingress-nginx repository +helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx + +# Use Helm to deploy an NGINX ingress controller +helm install nginx-ingress ingress-nginx/ingress-nginx ` + --namespace ingress-basic ` + --set controller.replicaCount=1 ` + --set controller.nodeSelector."kubernetes\.io/os"=linux ` + --set controller.image.registry=$ACR_URL ` + --set controller.image.image=$CONTROLLER_IMAGE ` + --set controller.image.tag=$CONTROLLER_TAG ` + --set controller.image.digest="" ` + --set controller.admissionWebhooks.patch.nodeSelector."kubernetes\.io/os"=linux ` + --set controller.admissionWebhooks.patch.image.registry=$ACR_URL ` + --set controller.admissionWebhooks.patch.image.image=$PATCH_IMAGE ` + --set controller.admissionWebhooks.patch.image.tag=$PATCH_TAG ` + --set defaultBackend.nodeSelector."kubernetes\.io/os"=linux ` + --set defaultBackend.image.registry=$ACR_URL ` + --set defaultBackend.image.image=$DEFAULTBACKEND_IMAGE ` + --set defaultBackend.image.tag=$DEFAULTBACKEND_TAG + +# Label the ingress-basic namespace to disable resource validation +kubectl label namespace ingress-basic cert-manager.io/disable-validation=true + +# Add the Jetstack Helm repository +helm repo add jetstack https://charts.jetstack.io + +# Update your local Helm chart repository cache +helm repo update + +# Install the cert-manager Helm chart +helm install cert-manager jetstack/cert-manager ` + --namespace ingress-basic ` + --version ${CERT_MANAGER_TAG} ` + --set installCRDs=true ` + --set nodeSelector."kubernetes\.io/os"=linux ` + --set image.repository=${ACR_URL}/${CERT_MANAGER_IMAGE_CONTROLLER} ` + --set image.tag=${CERT_MANAGER_TAG} ` + --set webhook.image.repository=${ACR_URL}/${CERT_MANAGER_IMAGE_WEBHOOK} ` + --set webhook.image.tag=${CERT_MANAGER_TAG} ` + --set cainjector.image.repository=${ACR_URL}/${CERT_MANAGER_IMAGE_CAINJECTOR} ` + --set cainjector.image.tag=${CERT_MANAGER_TAG} \ No newline at end of file diff --git a/etc/k8s/scripts/azure/push-images.ps1 b/etc/k8s/scripts/azure/push-images.ps1 new file mode 100644 index 0000000..a3e504d --- /dev/null +++ b/etc/k8s/scripts/azure/push-images.ps1 @@ -0,0 +1,22 @@ +az acr login --name volocr + +docker tag eventhub.dbmigrator:latest volocr.azurecr.io/eventhub.dbmigrator:latest +docker push volocr.azurecr.io/eventhub.dbmigrator:latest + +docker tag eventhub.www:latest volocr.azurecr.io/eventhub.www:latest +docker push volocr.azurecr.io/eventhub.www:latest + +docker tag eventhub.api:latest volocr.azurecr.io/eventhub.api:latest +docker push volocr.azurecr.io/eventhub.api:latest + +docker tag eventhub.admin:latest volocr.azurecr.io/eventhub.admin:latest +docker push volocr.azurecr.io/eventhub.admin:latest + +docker tag eventhub.admin-api:latest volocr.azurecr.io/eventhub.admin-api:latest +docker push volocr.azurecr.io/eventhub.admin-api:latest + +docker tag eventhub.account:latest volocr.azurecr.io/eventhub.account:latest +docker push volocr.azurecr.io/eventhub.account:latest + +docker tag eventhub.background-services:latest volocr.azurecr.io/eventhub.background-services:latest +docker push volocr.azurecr.io/eventhub.background-services:latest \ No newline at end of file diff --git a/etc/k8s/scripts/build-images.ps1 b/etc/k8s/scripts/build-images.ps1 new file mode 100644 index 0000000..e86165b --- /dev/null +++ b/etc/k8s/scripts/build-images.ps1 @@ -0,0 +1,63 @@ +$currentFolder = (Get-Item -Path "./" -Verbose).FullName +$slnFolder = Join-Path $currentFolder "../../../" +$dbmigratorFolder = Join-Path $slnFolder "src/EventHub.DbMigrator" +$webFolder = Join-Path $slnFolder "src/EventHub.Web" +$apiFolder = Join-Path $slnFolder "src/EventHub.HttpApi.Host" +$adminFolder = Join-Path $slnFolder "src/EventHub.Admin.Web" +$adminApiFolder = Join-Path $slnFolder "src/EventHub.Admin.HttpApi.Host" +$identityServerFolder = Join-Path $slnFolder "src/EventHub.IdentityServer" +$backgroundServicesFolder = Join-Path $slnFolder "src/EventHub.BackgroundServices" + +### DB MIGRATOR + +Write-Host "*** BUILDING DB MIGRATOR ****************" -ForegroundColor Green +Set-Location $dbmigratorFolder +dotnet publish -c Release +docker build -t eventhub.dbmigrator . + +### WEB (WWW) + +Write-Host "*** BUILDING WEB (WWW) ****************" -ForegroundColor Green +Set-Location $webFolder +dotnet publish -c Release +docker build -t eventhub.www . + +### API + +Write-Host "*** BUILDING API ****************" -ForegroundColor Green +Set-Location $apiFolder +dotnet publish -c Release +docker build -t eventhub.api . + +### ADMIN (BLAZOR) + +Write-Host "*** BUILDING ADMIN (BLAZOR) ****************" -ForegroundColor Green +Set-Location $adminFolder +dotnet publish -c Release +docker build -t eventhub.admin . + +### ADMIN API + +Write-Host "*** BUILDING ADMIN API ****************" -ForegroundColor Green +Set-Location $adminApiFolder +dotnet publish -c Release +docker build -t eventhub.admin-api . + +### IDENTITY SERVER (ACCOUNT) + +Write-Host "*** BUILDING IDENTITY SERVER (ACCOUNT) ****************" -ForegroundColor Green +Set-Location $identityServerFolder +dotnet publish -c Release +docker build -t eventhub.account . + +### BACKGROUND SERVICES + +Write-Host "*** BUILDING BACKGROUND SERVICES ****************" -ForegroundColor Green +Set-Location $backgroundServicesFolder +dotnet publish -c Release +docker build -t eventhub.background-services . + +### ALL COMPLETED + +Write-Host "ALL COMPLETED" -ForegroundColor Green +Set-Location $currentFolder \ No newline at end of file diff --git a/etc/k8s/scripts/minikube-load-images.ps1 b/etc/k8s/scripts/minikube-load-images.ps1 new file mode 100644 index 0000000..e63234c --- /dev/null +++ b/etc/k8s/scripts/minikube-load-images.ps1 @@ -0,0 +1,7 @@ +minikube image load eventhub.dbmigrator:latest +minikube image load eventhub.www:latest +minikube image load eventhub.api:latest +minikube image load eventhub.admin:latest +minikube image load eventhub.admin-api:latest +minikube image load eventhub.account:latest +minikube image load eventhub.background-services:latest \ No newline at end of file diff --git a/src/EventHub.Admin.HttpApi.Host/Dockerfile b/src/EventHub.Admin.HttpApi.Host/Dockerfile new file mode 100644 index 0000000..7dda575 --- /dev/null +++ b/src/EventHub.Admin.HttpApi.Host/Dockerfile @@ -0,0 +1,4 @@ + FROM mcr.microsoft.com/dotnet/aspnet:5.0 + COPY bin/Release/net5.0/publish/ app/ + WORKDIR /app + ENTRYPOINT ["dotnet", "EventHub.Admin.HttpApi.Host.dll"] \ No newline at end of file diff --git a/src/EventHub.Admin.HttpApi.Host/EventHubAdminHttpApiHostModule.cs b/src/EventHub.Admin.HttpApi.Host/EventHubAdminHttpApiHostModule.cs index 38ff481..17946a0 100644 --- a/src/EventHub.Admin.HttpApi.Host/EventHubAdminHttpApiHostModule.cs +++ b/src/EventHub.Admin.HttpApi.Host/EventHubAdminHttpApiHostModule.cs @@ -3,7 +3,9 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; +using EventHub.Admin.Utils; using EventHub.EntityFrameworkCore; +using EventHub.Web; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Cors; @@ -54,6 +56,7 @@ namespace EventHub.Admin ConfigureVirtualFileSystem(context); ConfigureRedis(context, configuration); ConfigureCors(context, configuration); + ConfigureCookies(context); ConfigureSwaggerServices(context, configuration); ConfigureBackgroundJobs(); } @@ -109,7 +112,7 @@ namespace EventHub.Admin private static void ConfigureSwaggerServices(ServiceConfigurationContext context, IConfiguration configuration) { context.Services.AddAbpSwaggerGenWithOAuth( - configuration["AuthServer:Authority"], + configuration[EventHubUrlOptions.GetAccountConfigKey()], new Dictionary { {"EventHubAdmin", "EventHub Admin API"} @@ -148,10 +151,7 @@ namespace EventHub.Admin { builder .WithOrigins( - configuration["App:CorsOrigins"] - .Split(",", StringSplitOptions.RemoveEmptyEntries) - .Select(o => o.RemovePostFix("/")) - .ToArray() + configuration[EventHubUrlOptions.GetAdminConfigKey()] ) .WithAbpExposedHeaders() .SetIsOriginAllowedToAllowWildcardSubdomains() @@ -162,6 +162,11 @@ namespace EventHub.Admin }); } + private void ConfigureCookies(ServiceConfigurationContext context) + { + context.Services.AddSameSiteCookiePolicy(); + } + public override void OnApplicationInitialization(ApplicationInitializationContext context) { var app = context.GetApplicationBuilder(); @@ -194,8 +199,9 @@ namespace EventHub.Admin app.UseErrorPage(); } + app.UseCookiePolicy(); app.UseCorrelationId(); - app.UseVirtualFiles(); + app.UseStaticFiles(); app.UseRouting(); app.UseCors(DefaultCorsPolicyName); app.UseAuthentication(); diff --git a/src/EventHub.Admin.HttpApi.Host/Program.cs b/src/EventHub.Admin.HttpApi.Host/Program.cs index fdb4ed3..076a07e 100644 --- a/src/EventHub.Admin.HttpApi.Host/Program.cs +++ b/src/EventHub.Admin.HttpApi.Host/Program.cs @@ -20,9 +20,7 @@ namespace EventHub.Admin .MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning) .Enrich.FromLogContext() .WriteTo.Async(c => c.File("Logs/logs.txt")) -#if DEBUG .WriteTo.Async(c => c.Console()) -#endif .CreateLogger(); try diff --git a/src/EventHub.Admin.HttpApi.Host/Utils/SameSiteCookiesServiceCollectionExtensions.cs b/src/EventHub.Admin.HttpApi.Host/Utils/SameSiteCookiesServiceCollectionExtensions.cs new file mode 100644 index 0000000..0895c29 --- /dev/null +++ b/src/EventHub.Admin.HttpApi.Host/Utils/SameSiteCookiesServiceCollectionExtensions.cs @@ -0,0 +1,71 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; + +namespace EventHub.Admin.Utils +{ + public static class SameSiteCookiesServiceCollectionExtensions + { + public static IServiceCollection AddSameSiteCookiePolicy(this IServiceCollection services) + { + services.Configure(options => + { + options.MinimumSameSitePolicy = SameSiteMode.Unspecified; + options.OnAppendCookie = cookieContext => + CheckSameSite(cookieContext.Context, cookieContext.CookieOptions); + options.OnDeleteCookie = cookieContext => + CheckSameSite(cookieContext.Context, cookieContext.CookieOptions); + }); + + return services; + } + + private static void CheckSameSite(HttpContext httpContext, CookieOptions options) + { + if (options.SameSite == SameSiteMode.None) + { + var userAgent = httpContext.Request.Headers["User-Agent"].ToString(); + if (!httpContext.Request.IsHttps || DisallowsSameSiteNone(userAgent)) + { + // For .NET Core < 3.1 set SameSite = (SameSiteMode)(-1) + options.SameSite = SameSiteMode.Unspecified; + } + } + } + + private static bool DisallowsSameSiteNone(string userAgent) + { + // Cover all iOS based browsers here. This includes: + // - Safari on iOS 12 for iPhone, iPod Touch, iPad + // - WkWebview on iOS 12 for iPhone, iPod Touch, iPad + // - Chrome on iOS 12 for iPhone, iPod Touch, iPad + // All of which are broken by SameSite=None, because they use the iOS networking stack + if (userAgent.Contains("CPU iPhone OS 12") || userAgent.Contains("iPad; CPU OS 12")) + { + return true; + } + + // Cover Mac OS X based browsers that use the Mac OS networking stack. This includes: + // - Safari on Mac OS X. + // This does not include: + // - Chrome on Mac OS X + // Because they do not use the Mac OS networking stack. + if (userAgent.Contains("Macintosh; Intel Mac OS X 10_14") && + userAgent.Contains("Version/") && userAgent.Contains("Safari")) + { + return true; + } + + // Cover Chrome 50-69, because some versions are broken by SameSite=None, + // and none in this range require it. + // Note: this covers some pre-Chromium Edge versions, + // but pre-Chromium Edge does not require SameSite=None. + if (userAgent.Contains("Chrome/5") || userAgent.Contains("Chrome/6")) + { + return true; + } + + return false; + } + } +} \ No newline at end of file diff --git a/src/EventHub.Admin.HttpApi.Host/appsettings.Development.json b/src/EventHub.Admin.HttpApi.Host/appsettings.Development.json deleted file mode 100644 index 2c63c08..0000000 --- a/src/EventHub.Admin.HttpApi.Host/appsettings.Development.json +++ /dev/null @@ -1,2 +0,0 @@ -{ -} diff --git a/src/EventHub.Admin.HttpApi.Host/appsettings.json b/src/EventHub.Admin.HttpApi.Host/appsettings.json index 7c2ab2d..aca9ac1 100644 --- a/src/EventHub.Admin.HttpApi.Host/appsettings.json +++ b/src/EventHub.Admin.HttpApi.Host/appsettings.json @@ -1,20 +1,14 @@ { - "App": { - "CorsOrigins": "https://*.openeventhub.com,https://localhost:44307,https://localhost:44308" - }, "ConnectionStrings": { "Default": "Host=localhost;Database=EventHub;Username=root;Password=root;Port=5432" }, "Redis": { - "Configuration": "127.0.0.1" + "Configuration": "localhost" }, "AuthServer": { "Authority": "https://localhost:44313", "RequireHttpsMetadata": "true", "SwaggerClientId": "EventHub_Swagger", "SwaggerClientSecret": "1q2w3e*" - }, - "StringEncryption": { - "DefaultPassPhrase": "TxVIZFPxK33czbbv" } } diff --git a/src/EventHub.Admin.Web/Dockerfile b/src/EventHub.Admin.Web/Dockerfile new file mode 100644 index 0000000..cdfeb3c --- /dev/null +++ b/src/EventHub.Admin.Web/Dockerfile @@ -0,0 +1,3 @@ +FROM nginx:latest +COPY ./bin/Release/net5.0/publish/wwwroot/ /usr/share/nginx/html/ +COPY ./nginx.conf /etc/nginx/conf.d/default.conf \ No newline at end of file diff --git a/src/EventHub.Admin.Web/nginx.conf b/src/EventHub.Admin.Web/nginx.conf new file mode 100644 index 0000000..4369baa --- /dev/null +++ b/src/EventHub.Admin.Web/nginx.conf @@ -0,0 +1,7 @@ +server { + listen 80; + location / { + root /usr/share/nginx/html; + try_files $uri /index.html; + } +} \ No newline at end of file diff --git a/src/EventHub.Admin.Web/wwwroot/appsettings.Development.json b/src/EventHub.Admin.Web/wwwroot/appsettings.Development.json deleted file mode 100644 index 0db3279..0000000 --- a/src/EventHub.Admin.Web/wwwroot/appsettings.Development.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - -} diff --git a/src/EventHub.Admin.Web/wwwroot/appsettings.Production.json b/src/EventHub.Admin.Web/wwwroot/appsettings.Production.json new file mode 100644 index 0000000..4be599b --- /dev/null +++ b/src/EventHub.Admin.Web/wwwroot/appsettings.Production.json @@ -0,0 +1,13 @@ +{ + "App": { + "SelfUrl": "https://admin.openeventhub.com" + }, + "AuthServer": { + "Authority": "https://account.openeventhub.com" + }, + "RemoteServices": { + "Default": { + "BaseUrl": "https://admin-api.openeventhub.com" + } + } +} diff --git a/src/EventHub.Admin.Web/wwwroot/appsettings.Staging.json b/src/EventHub.Admin.Web/wwwroot/appsettings.Staging.json new file mode 100644 index 0000000..52d847d --- /dev/null +++ b/src/EventHub.Admin.Web/wwwroot/appsettings.Staging.json @@ -0,0 +1,13 @@ +{ + "App": { + "SelfUrl": "https://eh-st-admin" + }, + "AuthServer": { + "Authority": "https://eh-st-account" + }, + "RemoteServices": { + "Default": { + "BaseUrl": "https://eh-st-admin-api" + } + } +} diff --git a/src/EventHub.BackgroundServices/Dockerfile b/src/EventHub.BackgroundServices/Dockerfile new file mode 100644 index 0000000..9cf1f9e --- /dev/null +++ b/src/EventHub.BackgroundServices/Dockerfile @@ -0,0 +1,4 @@ + FROM mcr.microsoft.com/dotnet/aspnet:5.0 + COPY bin/Release/net5.0/ app/ + WORKDIR /app + ENTRYPOINT ["dotnet", "EventHub.BackgroundServices.dll"] \ No newline at end of file diff --git a/src/EventHub.DbMigrator/Dockerfile b/src/EventHub.DbMigrator/Dockerfile new file mode 100644 index 0000000..175494f --- /dev/null +++ b/src/EventHub.DbMigrator/Dockerfile @@ -0,0 +1,4 @@ + FROM mcr.microsoft.com/dotnet/aspnet:5.0 + COPY bin/Release/net5.0/ app/ + WORKDIR /app + ENTRYPOINT ["dotnet", "EventHub.DbMigrator.dll"] \ No newline at end of file diff --git a/src/EventHub.Domain.Shared/EventHubDomainSharedModule.cs b/src/EventHub.Domain.Shared/EventHubDomainSharedModule.cs index 8370a52..efa5dc2 100644 --- a/src/EventHub.Domain.Shared/EventHubDomainSharedModule.cs +++ b/src/EventHub.Domain.Shared/EventHubDomainSharedModule.cs @@ -1,4 +1,6 @@ using EventHub.Localization; +using EventHub.Web; +using Microsoft.Extensions.DependencyInjection; using Volo.Abp.AuditLogging; using Volo.Abp.BackgroundJobs; using Volo.Abp.Identity; @@ -33,6 +35,8 @@ namespace EventHub public override void ConfigureServices(ServiceConfigurationContext context) { + var configuration = context.Services.GetConfiguration(); + Configure(options => { options.FileSets.AddEmbedded(); @@ -52,6 +56,8 @@ namespace EventHub { options.MapCodeNamespace("EventHub", typeof(EventHubResource)); }); + + Configure(configuration.GetSection("AppUrls")); } } } diff --git a/src/EventHub.Domain.Shared/Web/EventHubExternalUrls.cs b/src/EventHub.Domain.Shared/Web/EventHubExternalUrls.cs deleted file mode 100644 index e6d8c7a..0000000 --- a/src/EventHub.Domain.Shared/Web/EventHubExternalUrls.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace EventHub.Web -{ - public static class EventHubExternalUrls - { -#if DEBUG - public const string EhAccount = "https://localhost:44313"; - public const string EhApi = "https://localhost:44362"; - public const string EhAdmin = "https://localhost:44307"; - public const string EhWww = "https://localhost:44308"; -#else - // TODO: Change these production links - public const string EhAccount = "https://localhost:44313"; - public const string EhApi = "https://localhost:44362"; - public const string EhAdmin = "https://localhost:44307"; - public const string EhWww = "https://localhost:44308"; -#endif - } -} \ No newline at end of file diff --git a/src/EventHub.Domain.Shared/Web/EventHubUrlOptions.cs b/src/EventHub.Domain.Shared/Web/EventHubUrlOptions.cs new file mode 100644 index 0000000..5d758a1 --- /dev/null +++ b/src/EventHub.Domain.Shared/Web/EventHubUrlOptions.cs @@ -0,0 +1,49 @@ +namespace EventHub.Web +{ + public class EventHubUrlOptions + { + private const string ConfigurationName = "AppUrls"; + + public string Account { get; set; } = "https://localhost:44313"; + public string Www { get; set; } = "https://localhost:44308"; + public string Api { get; set; } = "https://localhost:44362"; + public string ApiInternal { get; set; } = "https://localhost:44362"; + public string Admin { get; set; } = "https://localhost:44307"; + public string AdminApi { get; set; } = "https://localhost:44305"; + + public static string GetAccountConfigKey() + { + return GetConfigKey(nameof(Account)); + } + + public static string GetWwwConfigKey() + { + return GetConfigKey(nameof(Www)); + } + + public static string GetApiInternalConfigKey() + { + return GetConfigKey(nameof(ApiInternal)); + } + + public static string GetApiConfigKey() + { + return GetConfigKey(nameof(Api)); + } + + public static string GetAdminConfigKey() + { + return GetConfigKey(nameof(Admin)); + } + + public static string GetAdminApiConfigKey() + { + return GetConfigKey(nameof(AdminApi)); + } + + private static string GetConfigKey(string appName) + { + return $"{ConfigurationName}:{appName}"; + } + } +} \ No newline at end of file diff --git a/src/EventHub.Domain/Emailing/EventHubEmailTemplateRenderingEngine.cs b/src/EventHub.Domain/Emailing/EventHubEmailTemplateRenderingEngine.cs index 623a3f5..9021183 100644 --- a/src/EventHub.Domain/Emailing/EventHubEmailTemplateRenderingEngine.cs +++ b/src/EventHub.Domain/Emailing/EventHubEmailTemplateRenderingEngine.cs @@ -5,6 +5,7 @@ using EventHub.Web; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; using Volo.Abp.TextTemplating; using Volo.Abp.TextTemplating.Scriban; @@ -18,15 +19,19 @@ namespace EventHub.Emailing )] public class EventHubEmailTemplateRenderingEngine : ScribanTemplateRenderingEngine { + private readonly EventHubUrlOptions _options; + public EventHubEmailTemplateRenderingEngine( ITemplateDefinitionManager templateDefinitionManager, ITemplateContentProvider templateContentProvider, - IStringLocalizerFactory stringLocalizerFactory + IStringLocalizerFactory stringLocalizerFactory, + IOptions options ) : base( templateDefinitionManager, templateContentProvider, stringLocalizerFactory) { + _options = options.Value; } public override async Task RenderAsync( @@ -41,7 +46,7 @@ namespace EventHub.Emailing } globalContext["current_year"] = DateTime.Today.Year; - globalContext["app_url"] = EventHubExternalUrls.EhWww; + globalContext["app_url"] = _options.Www; return await base.RenderAsync(templateName, model, cultureName, globalContext); } diff --git a/src/EventHub.Domain/EventHubDomainModule.cs b/src/EventHub.Domain/EventHubDomainModule.cs index 000b842..8c17cf5 100644 --- a/src/EventHub.Domain/EventHubDomainModule.cs +++ b/src/EventHub.Domain/EventHubDomainModule.cs @@ -34,7 +34,6 @@ namespace EventHub { options.FileSets.AddEmbedded(); }); - #if DEBUG context.Services.Replace(ServiceDescriptor.Singleton()); #endif diff --git a/src/EventHub.HttpApi.Host/Dockerfile b/src/EventHub.HttpApi.Host/Dockerfile new file mode 100644 index 0000000..b5bd5d9 --- /dev/null +++ b/src/EventHub.HttpApi.Host/Dockerfile @@ -0,0 +1,4 @@ + FROM mcr.microsoft.com/dotnet/aspnet:5.0 + COPY bin/Release/net5.0/publish/ app/ + WORKDIR /app + ENTRYPOINT ["dotnet", "EventHub.HttpApi.Host.dll"] \ No newline at end of file diff --git a/src/EventHub.HttpApi.Host/EventHubHttpApiHostModule.cs b/src/EventHub.HttpApi.Host/EventHubHttpApiHostModule.cs index 9b886ba..3769b07 100644 --- a/src/EventHub.HttpApi.Host/EventHubHttpApiHostModule.cs +++ b/src/EventHub.HttpApi.Host/EventHubHttpApiHostModule.cs @@ -11,6 +11,8 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using EventHub.EntityFrameworkCore; +using EventHub.Utils; +using EventHub.Web; using Microsoft.AspNetCore.Localization; using StackExchange.Redis; using Microsoft.OpenApi.Models; @@ -26,6 +28,7 @@ using Volo.Abp.Caching.StackExchangeRedis; using Volo.Abp.Localization; using Volo.Abp.Modularity; using Volo.Abp.Swashbuckle; +using Volo.Abp.UI.Navigation.Urls; using Volo.Abp.VirtualFileSystem; namespace EventHub @@ -55,6 +58,7 @@ namespace EventHub ConfigureVirtualFileSystem(context); ConfigureRedis(context, configuration); ConfigureCors(context, configuration); + ConfigureCookies(context); ConfigureSwaggerServices(context, configuration); ConfigureBackgroundJobs(); } @@ -110,7 +114,7 @@ namespace EventHub private static void ConfigureSwaggerServices(ServiceConfigurationContext context, IConfiguration configuration) { context.Services.AddAbpSwaggerGenWithOAuth( - configuration["AuthServer:Authority"], + configuration[EventHubUrlOptions.GetAccountConfigKey()], new Dictionary { {"EventHub", "EventHub API"} @@ -149,10 +153,7 @@ namespace EventHub { builder .WithOrigins( - configuration["App:CorsOrigins"] - .Split(",", StringSplitOptions.RemoveEmptyEntries) - .Select(o => o.RemovePostFix("/")) - .ToArray() + configuration[EventHubUrlOptions.GetWwwConfigKey()] ) .WithAbpExposedHeaders() .SetIsOriginAllowedToAllowWildcardSubdomains() @@ -163,6 +164,11 @@ namespace EventHub }); } + private void ConfigureCookies(ServiceConfigurationContext context) + { + context.Services.AddSameSiteCookiePolicy(); + } + public override void OnApplicationInitialization(ApplicationInitializationContext context) { var app = context.GetApplicationBuilder(); @@ -172,6 +178,12 @@ namespace EventHub { app.UseDeveloperExceptionPage(); } + + app.Use((context, next) => + { + context.Request.Scheme = "https"; + return next(); + }); var supportedCultures = new[] { @@ -195,8 +207,9 @@ namespace EventHub app.UseErrorPage(); } + app.UseCookiePolicy(); app.UseCorrelationId(); - app.UseVirtualFiles(); + app.UseStaticFiles(); app.UseRouting(); app.UseCors(DefaultCorsPolicyName); app.UseAuthentication(); diff --git a/src/EventHub.HttpApi.Host/Program.cs b/src/EventHub.HttpApi.Host/Program.cs index 08c00d8..1bf31ea 100644 --- a/src/EventHub.HttpApi.Host/Program.cs +++ b/src/EventHub.HttpApi.Host/Program.cs @@ -20,9 +20,7 @@ namespace EventHub .MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning) .Enrich.FromLogContext() .WriteTo.Async(c => c.File("Logs/logs.txt")) -#if DEBUG .WriteTo.Async(c => c.Console()) -#endif .CreateLogger(); try diff --git a/src/EventHub.HttpApi.Host/Utils/SameSiteCookiesServiceCollectionExtensions.cs b/src/EventHub.HttpApi.Host/Utils/SameSiteCookiesServiceCollectionExtensions.cs new file mode 100644 index 0000000..2b35fe2 --- /dev/null +++ b/src/EventHub.HttpApi.Host/Utils/SameSiteCookiesServiceCollectionExtensions.cs @@ -0,0 +1,71 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; + +namespace EventHub.Utils +{ + public static class SameSiteCookiesServiceCollectionExtensions + { + public static IServiceCollection AddSameSiteCookiePolicy(this IServiceCollection services) + { + services.Configure(options => + { + options.MinimumSameSitePolicy = SameSiteMode.Unspecified; + options.OnAppendCookie = cookieContext => + CheckSameSite(cookieContext.Context, cookieContext.CookieOptions); + options.OnDeleteCookie = cookieContext => + CheckSameSite(cookieContext.Context, cookieContext.CookieOptions); + }); + + return services; + } + + private static void CheckSameSite(HttpContext httpContext, CookieOptions options) + { + if (options.SameSite == SameSiteMode.None) + { + var userAgent = httpContext.Request.Headers["User-Agent"].ToString(); + if (!httpContext.Request.IsHttps || DisallowsSameSiteNone(userAgent)) + { + // For .NET Core < 3.1 set SameSite = (SameSiteMode)(-1) + options.SameSite = SameSiteMode.Unspecified; + } + } + } + + private static bool DisallowsSameSiteNone(string userAgent) + { + // Cover all iOS based browsers here. This includes: + // - Safari on iOS 12 for iPhone, iPod Touch, iPad + // - WkWebview on iOS 12 for iPhone, iPod Touch, iPad + // - Chrome on iOS 12 for iPhone, iPod Touch, iPad + // All of which are broken by SameSite=None, because they use the iOS networking stack + if (userAgent.Contains("CPU iPhone OS 12") || userAgent.Contains("iPad; CPU OS 12")) + { + return true; + } + + // Cover Mac OS X based browsers that use the Mac OS networking stack. This includes: + // - Safari on Mac OS X. + // This does not include: + // - Chrome on Mac OS X + // Because they do not use the Mac OS networking stack. + if (userAgent.Contains("Macintosh; Intel Mac OS X 10_14") && + userAgent.Contains("Version/") && userAgent.Contains("Safari")) + { + return true; + } + + // Cover Chrome 50-69, because some versions are broken by SameSite=None, + // and none in this range require it. + // Note: this covers some pre-Chromium Edge versions, + // but pre-Chromium Edge does not require SameSite=None. + if (userAgent.Contains("Chrome/5") || userAgent.Contains("Chrome/6")) + { + return true; + } + + return false; + } + } +} \ No newline at end of file diff --git a/src/EventHub.HttpApi.Host/appsettings.Development.json b/src/EventHub.HttpApi.Host/appsettings.Development.json deleted file mode 100644 index 2c63c08..0000000 --- a/src/EventHub.HttpApi.Host/appsettings.Development.json +++ /dev/null @@ -1,2 +0,0 @@ -{ -} diff --git a/src/EventHub.HttpApi.Host/appsettings.json b/src/EventHub.HttpApi.Host/appsettings.json index 7c2ab2d..aca9ac1 100644 --- a/src/EventHub.HttpApi.Host/appsettings.json +++ b/src/EventHub.HttpApi.Host/appsettings.json @@ -1,20 +1,14 @@ { - "App": { - "CorsOrigins": "https://*.openeventhub.com,https://localhost:44307,https://localhost:44308" - }, "ConnectionStrings": { "Default": "Host=localhost;Database=EventHub;Username=root;Password=root;Port=5432" }, "Redis": { - "Configuration": "127.0.0.1" + "Configuration": "localhost" }, "AuthServer": { "Authority": "https://localhost:44313", "RequireHttpsMetadata": "true", "SwaggerClientId": "EventHub_Swagger", "SwaggerClientSecret": "1q2w3e*" - }, - "StringEncryption": { - "DefaultPassPhrase": "TxVIZFPxK33czbbv" } } diff --git a/src/EventHub.IdentityServer/Dockerfile b/src/EventHub.IdentityServer/Dockerfile new file mode 100644 index 0000000..20a0003 --- /dev/null +++ b/src/EventHub.IdentityServer/Dockerfile @@ -0,0 +1,4 @@ + FROM mcr.microsoft.com/dotnet/aspnet:5.0 + COPY bin/Release/net5.0/publish/ app/ + WORKDIR /app + ENTRYPOINT ["dotnet", "EventHub.IdentityServer.dll"] \ No newline at end of file diff --git a/src/EventHub.IdentityServer/EventHub.IdentityServer.csproj b/src/EventHub.IdentityServer/EventHub.IdentityServer.csproj index 8d54cd5..dce5b30 100644 --- a/src/EventHub.IdentityServer/EventHub.IdentityServer.csproj +++ b/src/EventHub.IdentityServer/EventHub.IdentityServer.csproj @@ -20,6 +20,10 @@ + + + Always + diff --git a/src/EventHub.IdentityServer/EventHubIdentityServerModule.cs b/src/EventHub.IdentityServer/EventHubIdentityServerModule.cs index 08898db..55d63bc 100644 --- a/src/EventHub.IdentityServer/EventHubIdentityServerModule.cs +++ b/src/EventHub.IdentityServer/EventHubIdentityServerModule.cs @@ -1,6 +1,5 @@ -using System; using System.IO; -using System.Linq; +using System.Security.Cryptography.X509Certificates; using Localization.Resources.AbpUi; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Cors; @@ -9,16 +8,19 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using EventHub.EntityFrameworkCore; using EventHub.Localization; +using EventHub.Utils; using EventHub.Web; using EventHub.Web.Theme; using EventHub.Web.Theme.Bundling; using IdentityServer4.Configuration; +using IdentityServer4.Extensions; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; using StackExchange.Redis; using Volo.Abp; using Volo.Abp.Account; using Volo.Abp.Account.Web; using Volo.Abp.AspNetCore.Mvc.UI.Bundling; -using Volo.Abp.AspNetCore.Mvc.UI.Components.LayoutHook; using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared; using Volo.Abp.AspNetCore.Serilog; using Volo.Abp.Auditing; @@ -26,6 +28,7 @@ using Volo.Abp.Autofac; using Volo.Abp.BackgroundJobs; using Volo.Abp.Caching; using Volo.Abp.Caching.StackExchangeRedis; +using Volo.Abp.IdentityServer; using Volo.Abp.Localization; using Volo.Abp.Modularity; using Volo.Abp.UI.Navigation.Urls; @@ -46,6 +49,40 @@ namespace EventHub { private const string DefaultCorsPolicyName = "Default"; + public override void PreConfigureServices(ServiceConfigurationContext context) + { + var hostingEnvironment = context.Services.GetHostingEnvironment(); + + if (!hostingEnvironment.IsDevelopment()) + { + var configuration = context.Services.GetConfiguration(); + + PreConfigure(options => + { + options.AddDeveloperSigningCredential = false; + }); + + PreConfigure(builder => + { + builder.AddSigningCredential(GetSigningCertificate(hostingEnvironment, configuration)); + }); + } + } + + private X509Certificate2 GetSigningCertificate(IWebHostEnvironment hostingEnv, IConfiguration configuration) + { + var fileName = "account.openeventhub.pfx"; + var passPhrase = "a8202f07-66e5-4619-be07-72ba76fde97f"; + var file = Path.Combine(hostingEnv.ContentRootPath, fileName); + + if (!File.Exists(file)) + { + throw new FileNotFoundException($"Signing Certificate couldn't found: {file}"); + } + + return new X509Certificate2(file, passPhrase); + } + public override void ConfigureServices(ServiceConfigurationContext context) { var hostingEnvironment = context.Services.GetHostingEnvironment(); @@ -79,17 +116,11 @@ namespace EventHub options.ApplicationName = "AuthServer"; }); - Configure(options => - { - options.Applications["MVC"].RootUrl = EventHubExternalUrls.EhAccount; - }); - Configure(options => { - options.IssuerUri = EventHubExternalUrls.EhAccount; + options.IssuerUri = configuration[EventHubUrlOptions.GetAccountConfigKey()]; }); - if (hostingEnvironment.IsDevelopment()) { Configure(options => @@ -102,8 +133,15 @@ namespace EventHub Configure(options => { - options.Applications["MVC"].RootUrl = configuration["App:SelfUrl"]; - options.RedirectAllowedUrls.AddRange(configuration["App:RedirectAllowedUrls"].Split(',')); + options.Applications["MVC"].RootUrl = configuration[EventHubUrlOptions.GetAccountConfigKey()]; + options.RedirectAllowedUrls.AddRange( + new[] + { + configuration[EventHubUrlOptions.GetWwwConfigKey()], + configuration[EventHubUrlOptions.GetAdminConfigKey()], + configuration[EventHubUrlOptions.GetApiConfigKey()], + configuration[EventHubUrlOptions.GetAdminApiConfigKey()] + }); }); Configure(options => @@ -127,10 +165,10 @@ namespace EventHub { builder .WithOrigins( - configuration["App:CorsOrigins"] - .Split(",", StringSplitOptions.RemoveEmptyEntries) - .Select(o => o.RemovePostFix("/")) - .ToArray() + configuration[EventHubUrlOptions.GetWwwConfigKey()], + configuration[EventHubUrlOptions.GetApiConfigKey()], + configuration[EventHubUrlOptions.GetAdminConfigKey()], + configuration[EventHubUrlOptions.GetAdminApiConfigKey()] ) .WithAbpExposedHeaders() .SetIsOriginAllowedToAllowWildcardSubdomains() @@ -139,13 +177,26 @@ namespace EventHub .AllowCredentials(); }); }); + + context.Services.AddSameSiteCookiePolicy(); } public override void OnApplicationInitialization(ApplicationInitializationContext context) { var app = context.GetApplicationBuilder(); var env = context.GetEnvironment(); + var configuration = context.ServiceProvider.GetRequiredService(); + app.Use(async (ctx, next) => + { + if (ctx.Request.Headers.ContainsKey("from-ingress")) + { + ctx.SetIdentityServerOrigin(configuration[EventHubUrlOptions.GetAccountConfigKey()]); + } + + await next(); + }); + if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); @@ -157,9 +208,10 @@ namespace EventHub { app.UseErrorPage(); } - + + app.UseCookiePolicy(); app.UseCorrelationId(); - app.UseVirtualFiles(); + app.UseStaticFiles(); app.UseRouting(); app.UseCors(DefaultCorsPolicyName); app.UseAuthentication(); diff --git a/src/EventHub.IdentityServer/Program.cs b/src/EventHub.IdentityServer/Program.cs index ef4acd5..c65563b 100644 --- a/src/EventHub.IdentityServer/Program.cs +++ b/src/EventHub.IdentityServer/Program.cs @@ -20,9 +20,7 @@ namespace EventHub .MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning) .Enrich.FromLogContext() .WriteTo.Async(c => c.File("Logs/logs.txt")) -#if DEBUG .WriteTo.Async(c => c.Console()) -#endif .CreateLogger(); try diff --git a/src/EventHub.IdentityServer/Utils/SameSiteCookiesServiceCollectionExtensions.cs b/src/EventHub.IdentityServer/Utils/SameSiteCookiesServiceCollectionExtensions.cs new file mode 100644 index 0000000..2b35fe2 --- /dev/null +++ b/src/EventHub.IdentityServer/Utils/SameSiteCookiesServiceCollectionExtensions.cs @@ -0,0 +1,71 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; + +namespace EventHub.Utils +{ + public static class SameSiteCookiesServiceCollectionExtensions + { + public static IServiceCollection AddSameSiteCookiePolicy(this IServiceCollection services) + { + services.Configure(options => + { + options.MinimumSameSitePolicy = SameSiteMode.Unspecified; + options.OnAppendCookie = cookieContext => + CheckSameSite(cookieContext.Context, cookieContext.CookieOptions); + options.OnDeleteCookie = cookieContext => + CheckSameSite(cookieContext.Context, cookieContext.CookieOptions); + }); + + return services; + } + + private static void CheckSameSite(HttpContext httpContext, CookieOptions options) + { + if (options.SameSite == SameSiteMode.None) + { + var userAgent = httpContext.Request.Headers["User-Agent"].ToString(); + if (!httpContext.Request.IsHttps || DisallowsSameSiteNone(userAgent)) + { + // For .NET Core < 3.1 set SameSite = (SameSiteMode)(-1) + options.SameSite = SameSiteMode.Unspecified; + } + } + } + + private static bool DisallowsSameSiteNone(string userAgent) + { + // Cover all iOS based browsers here. This includes: + // - Safari on iOS 12 for iPhone, iPod Touch, iPad + // - WkWebview on iOS 12 for iPhone, iPod Touch, iPad + // - Chrome on iOS 12 for iPhone, iPod Touch, iPad + // All of which are broken by SameSite=None, because they use the iOS networking stack + if (userAgent.Contains("CPU iPhone OS 12") || userAgent.Contains("iPad; CPU OS 12")) + { + return true; + } + + // Cover Mac OS X based browsers that use the Mac OS networking stack. This includes: + // - Safari on Mac OS X. + // This does not include: + // - Chrome on Mac OS X + // Because they do not use the Mac OS networking stack. + if (userAgent.Contains("Macintosh; Intel Mac OS X 10_14") && + userAgent.Contains("Version/") && userAgent.Contains("Safari")) + { + return true; + } + + // Cover Chrome 50-69, because some versions are broken by SameSite=None, + // and none in this range require it. + // Note: this covers some pre-Chromium Edge versions, + // but pre-Chromium Edge does not require SameSite=None. + if (userAgent.Contains("Chrome/5") || userAgent.Contains("Chrome/6")) + { + return true; + } + + return false; + } + } +} \ No newline at end of file diff --git a/src/EventHub.IdentityServer/account.openeventhub.pfx b/src/EventHub.IdentityServer/account.openeventhub.pfx new file mode 100644 index 0000000..e82db7f Binary files /dev/null and b/src/EventHub.IdentityServer/account.openeventhub.pfx differ diff --git a/src/EventHub.IdentityServer/appsettings.Development.json b/src/EventHub.IdentityServer/appsettings.Development.json deleted file mode 100644 index 2c63c08..0000000 --- a/src/EventHub.IdentityServer/appsettings.Development.json +++ /dev/null @@ -1,2 +0,0 @@ -{ -} diff --git a/src/EventHub.IdentityServer/appsettings.json b/src/EventHub.IdentityServer/appsettings.json index c9e8b26..85f4ef3 100644 --- a/src/EventHub.IdentityServer/appsettings.json +++ b/src/EventHub.IdentityServer/appsettings.json @@ -1,27 +1,8 @@ { - "App": { - "SelfUrl": "https://localhost:44313", - "CorsOrigins": "https://*.EventHub.com,http://localhost:4200,https://localhost:44307,https://localhost:44362", - "RedirectAllowedUrls": "http://localhost:4200,https://localhost:44307" - }, "ConnectionStrings": { "Default": "Host=localhost;Database=EventHub;Username=root;Password=root;Port=5432" }, "Redis": { - "Configuration": "127.0.0.1" - }, - "StringEncryption": { - "DefaultPassPhrase": "TxVIZFPxK33czbbv" - }, - "Settings": { - "Abp.Mailing.Smtp.Host": "127.0.0.1", - "Abp.Mailing.Smtp.Port": "25", - "Abp.Mailing.Smtp.UserName": "", - "Abp.Mailing.Smtp.Password": "", - "Abp.Mailing.Smtp.Domain": "", - "Abp.Mailing.Smtp.EnableSsl": "false", - "Abp.Mailing.Smtp.UseDefaultCredentials": "true", - "Abp.Mailing.DefaultFromAddress": "noreply@abp.io", - "Abp.Mailing.DefaultFromDisplayName": "ABP application" + "Configuration": "localhost" } } diff --git a/src/EventHub.Web.Theme/Themes/EventHub/Components/Footer/Default.cshtml b/src/EventHub.Web.Theme/Themes/EventHub/Components/Footer/Default.cshtml index 149877e..a528740 100644 --- a/src/EventHub.Web.Theme/Themes/EventHub/Components/Footer/Default.cshtml +++ b/src/EventHub.Web.Theme/Themes/EventHub/Components/Footer/Default.cshtml @@ -1,7 +1,9 @@ @using EventHub.Web @using Microsoft.AspNetCore.Http.Extensions +@using Microsoft.Extensions.Options @using Volo.Abp.Users @inject ICurrentUser CurrentUser +@inject IOptions UrlOptions