From cff588be6bc44675a4471d4bdf75bcde603f496f Mon Sep 17 00:00:00 2001
From: Thomas Staub <thomas.staub@gibb.ch>
Date: Tue, 12 Sep 2023 10:01:49 +0200
Subject: [PATCH] Update Nuget 1.0.16

---
 .../Play.Catalog.Service.csproj               |   2 +-
 Play.Common/README.md                         |  12 ++-
 .../Play.Common/Configuration/Extensions.cs   |  29 ++++++
 .../Play.Common/HealthChecks/Extensions.cs    |  53 +++++++++++
 .../HealthChecks/MongoDbHealthCheck.cs        |  33 +++++++
 .../src/Play.Common/Identity/Extensions.cs    |   8 +-
 .../src/Play.Common/MassTransit/Extensions.cs |  79 ++++++++++++++++
 .../src/Play.Common/Play.Common.csproj        |   5 +-
 .../Play.Common/Settings/MongoDbSettings.cs   |  10 ++-
 .../Settings/ServiceBusSettings.cs            |   7 ++
 .../Play.Common/Settings/ServiceSettings.cs   |   2 +
 Play.Common1/.gitignore                       |   2 +
 Play.Common1/.vscode/tasks.json               |  46 ++++++++++
 Play.Common1/README.md                        |  16 ++++
 .../Play.Common/DesignTimeBuild/.dtbcache.v2  | Bin
 ...55a3eb04-01a5-4be6-9993-d1a5d9968f14.vsidx | Bin
 .../Play.Common/FileContentIndex/read.lock    |   0
 .../.vs/Play.Common/v17/.futdcache.v2         | Bin
 .../src/Play.Common/.vs/Play.Common/v17/.suo  | Bin
 .../Play.Common/HealthChecks/Extensions.cs    |  53 +++++++++++
 .../HealthChecks/MongoDbHealthCheck.cs        |  33 +++++++
 Play.Common1/src/Play.Common/IEntity.cs       |   9 ++
 Play.Common1/src/Play.Common/IRepository.cs   |  18 ++++
 .../Identity/ConfigureJwtBearerOptions.cs     |  62 +++++++++++++
 .../src/Play.Common/Identity/Extensions.cs    |  16 ++++
 .../src/Play.Common/MassTransit/Extensions.cs |  52 +++++++++++
 .../src/Play.Common/MongoDB/Extensions.cs     |  42 +++++++++
 .../Play.Common/MongoDB/MongoRepository.cs    |  68 ++++++++++++++
 .../src/Play.Common/Play.Common.csproj        |  20 +++++
 .../src/Play.Common/Play.Common.sln           |   0
 .../Play.Common/Settings/MongoDbSettings.cs   |  11 +++
 .../Play.Common/Settings/RabbitMQSettings.cs  |   7 ++
 .../Settings/ServiceBusSettings.cs            |   7 ++
 .../Play.Common/Settings/ServiceSettings.cs   |   8 ++
 .../src/Play.Common/nuget.config              |   0
 Play.Identity/kubernetes/identity.yaml        |  84 ++++++++++++++++++
 Play.Identity/kubernetes/singning-cer.yaml    |  11 +++
 .../Play.Identity.Service.csproj              |   2 +-
 .../src/Play.Identity.Service/Program.cs      |   5 ++
 Play.Infra/cert-manager/acme-challenge.yaml   |  21 +++++
 Play.Infra/cert-manager/cluster-issuer.yaml   |  14 +++
 Play.Infra/emissary-ingress/host.yaml         |  10 +++
 Play.Infra/emissary-ingress/listener.yaml     |  24 +++++
 Play.Infra/emissary-ingress/mappings.yaml     |  50 +++++++++++
 .../emissary-ingress/tls-certificate.yaml     |  11 +++
 .../Play.Inventory.Service.csproj             |   2 +-
 .../Play.Trading.Service.csproj               |   2 +-
 README.md                                     |  15 +++-
 packages/Play.Common.1.0.15.nupkg             | Bin 0 -> 14224 bytes
 packages/Play.Common.1.0.16.nupkg             | Bin 0 -> 14224 bytes
 50 files changed, 949 insertions(+), 12 deletions(-)
 create mode 100644 Play.Common/src/Play.Common/Configuration/Extensions.cs
 create mode 100644 Play.Common/src/Play.Common/HealthChecks/Extensions.cs
 create mode 100644 Play.Common/src/Play.Common/HealthChecks/MongoDbHealthCheck.cs
 create mode 100644 Play.Common/src/Play.Common/Settings/ServiceBusSettings.cs
 create mode 100644 Play.Common1/.gitignore
 create mode 100644 Play.Common1/.vscode/tasks.json
 create mode 100644 Play.Common1/README.md
 rename {Play.Common => Play.Common1}/src/Play.Common/.vs/Play.Common/DesignTimeBuild/.dtbcache.v2 (100%)
 rename {Play.Common => Play.Common1}/src/Play.Common/.vs/Play.Common/FileContentIndex/55a3eb04-01a5-4be6-9993-d1a5d9968f14.vsidx (100%)
 rename {Play.Common => Play.Common1}/src/Play.Common/.vs/Play.Common/FileContentIndex/read.lock (100%)
 rename {Play.Common => Play.Common1}/src/Play.Common/.vs/Play.Common/v17/.futdcache.v2 (100%)
 rename {Play.Common => Play.Common1}/src/Play.Common/.vs/Play.Common/v17/.suo (100%)
 create mode 100644 Play.Common1/src/Play.Common/HealthChecks/Extensions.cs
 create mode 100644 Play.Common1/src/Play.Common/HealthChecks/MongoDbHealthCheck.cs
 create mode 100644 Play.Common1/src/Play.Common/IEntity.cs
 create mode 100644 Play.Common1/src/Play.Common/IRepository.cs
 create mode 100644 Play.Common1/src/Play.Common/Identity/ConfigureJwtBearerOptions.cs
 create mode 100644 Play.Common1/src/Play.Common/Identity/Extensions.cs
 create mode 100644 Play.Common1/src/Play.Common/MassTransit/Extensions.cs
 create mode 100644 Play.Common1/src/Play.Common/MongoDB/Extensions.cs
 create mode 100644 Play.Common1/src/Play.Common/MongoDB/MongoRepository.cs
 create mode 100644 Play.Common1/src/Play.Common/Play.Common.csproj
 rename {Play.Common => Play.Common1}/src/Play.Common/Play.Common.sln (100%)
 create mode 100644 Play.Common1/src/Play.Common/Settings/MongoDbSettings.cs
 create mode 100644 Play.Common1/src/Play.Common/Settings/RabbitMQSettings.cs
 create mode 100644 Play.Common1/src/Play.Common/Settings/ServiceBusSettings.cs
 create mode 100644 Play.Common1/src/Play.Common/Settings/ServiceSettings.cs
 rename {Play.Common => Play.Common1}/src/Play.Common/nuget.config (100%)
 create mode 100644 Play.Identity/kubernetes/identity.yaml
 create mode 100644 Play.Identity/kubernetes/singning-cer.yaml
 create mode 100644 Play.Infra/cert-manager/acme-challenge.yaml
 create mode 100644 Play.Infra/cert-manager/cluster-issuer.yaml
 create mode 100644 Play.Infra/emissary-ingress/host.yaml
 create mode 100644 Play.Infra/emissary-ingress/listener.yaml
 create mode 100644 Play.Infra/emissary-ingress/mappings.yaml
 create mode 100644 Play.Infra/emissary-ingress/tls-certificate.yaml
 create mode 100644 packages/Play.Common.1.0.15.nupkg
 create mode 100644 packages/Play.Common.1.0.16.nupkg

diff --git a/Play.Catalog/src/Play.Catalog.Service/Play.Catalog.Service.csproj b/Play.Catalog/src/Play.Catalog.Service/Play.Catalog.Service.csproj
index 484f3df..0e5659a 100644
--- a/Play.Catalog/src/Play.Catalog.Service/Play.Catalog.Service.csproj
+++ b/Play.Catalog/src/Play.Catalog.Service/Play.Catalog.Service.csproj
@@ -5,7 +5,7 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="Play.Common" Version="1.0.13" />
+    <PackageReference Include="Play.Common" Version="1.0.16" />
     <PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
   </ItemGroup>
 
diff --git a/Play.Common/README.md b/Play.Common/README.md
index 5da64cc..536bd68 100644
--- a/Play.Common/README.md
+++ b/Play.Common/README.md
@@ -1,9 +1,15 @@
-dotnet pack src\Play.Common\ --configuration Release -p:PackageVersion=1.0.13  -o ..\packages
+From Root directory
 
-Wechseln ins Verzeichniss play.Common
+dotnet pack .\Play.Common\src\Play.Common\ --configuration Release -p:PackageVersion=1.0.14  -o .\packages
 
-dotnet nuget push Play.Common.1.0.13.nupkg --source https://git.gibb.ch/api/v4/projects/5940/packages/nuget/index.json --api-key glpat-xr4z39bn9pBiWQcygXJn
 
 
 
 
+Wechseln ins Verzeichniss packages
+
+dotnet nuget push .\packages\Play.Common.1.0.15.nupkg --source https://git.gibb.ch/api/v4/projects/5940/packages/nuget/index.json --api-key glpat-8GxsWezmB9YrpVnGygyg
+
+
+dotnet nuget push .\packages\Play.Catalog.Contracts.1.0.1.nupkg --source https://git.gibb.ch/api/v4/projects/5940/packages/nuget/index.json --api-key glpat-8GxsWezmB9YrpVnGygyg
+
diff --git a/Play.Common/src/Play.Common/Configuration/Extensions.cs b/Play.Common/src/Play.Common/Configuration/Extensions.cs
new file mode 100644
index 0000000..94994f9
--- /dev/null
+++ b/Play.Common/src/Play.Common/Configuration/Extensions.cs
@@ -0,0 +1,29 @@
+using System;
+using Azure.Identity;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Hosting;
+using Play.Common.Settings;
+
+namespace Play.Common.Configuration
+{
+    public static class Extensions
+    {
+        public static IHostBuilder ConfigureAzureKeyVault(this IHostBuilder builder)
+        {
+            return builder.ConfigureAppConfiguration((context, configurationBuilder) =>
+            {
+                if (context.HostingEnvironment.IsProduction())
+                {
+                    var configuration = configurationBuilder.Build();
+                    var serviceSettings = configuration.GetSection(nameof(ServiceSettings))
+                                                       .Get<ServiceSettings>();
+
+                    configurationBuilder.AddAzureKeyVault(
+                        new Uri($"https://{serviceSettings.KeyVaultName}.vault.azure.net/"),
+                        new DefaultAzureCredential()
+                    );
+                }
+            });
+        }
+    }
+}
\ No newline at end of file
diff --git a/Play.Common/src/Play.Common/HealthChecks/Extensions.cs b/Play.Common/src/Play.Common/HealthChecks/Extensions.cs
new file mode 100644
index 0000000..70be04c
--- /dev/null
+++ b/Play.Common/src/Play.Common/HealthChecks/Extensions.cs
@@ -0,0 +1,53 @@
+using System;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Diagnostics.HealthChecks;
+using Microsoft.AspNetCore.Routing;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Diagnostics.HealthChecks;
+using MongoDB.Driver;
+using Play.Common.Settings;
+
+namespace Play.Common.HealthChecks
+{
+    public static class Extensions
+    {
+        private const string MongoCheckName = "mongodb";
+        private const string ReadyTagName = "ready";
+        private const string LiveTagName = "live";
+        private const string HealthEndpoint = "health";
+        private const int DefaultSeconds = 3;
+
+        public static IHealthChecksBuilder AddMongoDb(
+            this IHealthChecksBuilder builder,
+            TimeSpan? timeout = default)
+        {
+            return builder.Add(new HealthCheckRegistration(
+                    MongoCheckName,
+                    serviceProvider =>
+                    {
+                        var configuration = serviceProvider.GetService<IConfiguration>();
+                        var mongoDbSettings = configuration.GetSection(nameof(MongoDbSettings))
+                                                           .Get<MongoDbSettings>();
+                        var mongoClient = new MongoClient(mongoDbSettings.ConnectionString);
+                        return new MongoDbHealthCheck(mongoClient);
+                    },
+                    HealthStatus.Unhealthy,
+                    new[] { ReadyTagName },
+                    TimeSpan.FromSeconds(DefaultSeconds)
+                ));
+        }
+
+        public static void MapPlayEconomyHealthChecks(this IEndpointRouteBuilder endpoints)
+        {
+            endpoints.MapHealthChecks($"/{HealthEndpoint}/{ReadyTagName}", new HealthCheckOptions()
+            {
+                Predicate = (check) => check.Tags.Contains(ReadyTagName)
+            });
+            endpoints.MapHealthChecks($"/{HealthEndpoint}/{LiveTagName}", new HealthCheckOptions()
+            {
+                Predicate = (check) => false
+            });
+        }
+    }
+}
\ No newline at end of file
diff --git a/Play.Common/src/Play.Common/HealthChecks/MongoDbHealthCheck.cs b/Play.Common/src/Play.Common/HealthChecks/MongoDbHealthCheck.cs
new file mode 100644
index 0000000..481f5af
--- /dev/null
+++ b/Play.Common/src/Play.Common/HealthChecks/MongoDbHealthCheck.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.Extensions.Diagnostics.HealthChecks;
+using MongoDB.Driver;
+
+namespace Play.Common.HealthChecks
+{
+    public class MongoDbHealthCheck : IHealthCheck
+    {
+        private readonly MongoClient client;
+
+        public MongoDbHealthCheck(MongoClient client)
+        {
+            this.client = client;
+        }
+
+        public async Task<HealthCheckResult> CheckHealthAsync(
+            HealthCheckContext context, 
+            CancellationToken cancellationToken = default)
+        {
+            try
+            {
+                 await client.ListDatabaseNamesAsync(cancellationToken);
+                 return HealthCheckResult.Healthy();
+            }
+            catch (Exception ex)
+            {
+                return HealthCheckResult.Unhealthy(exception: ex);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Play.Common/src/Play.Common/Identity/Extensions.cs b/Play.Common/src/Play.Common/Identity/Extensions.cs
index 86e9936..e43c56c 100644
--- a/Play.Common/src/Play.Common/Identity/Extensions.cs
+++ b/Play.Common/src/Play.Common/Identity/Extensions.cs
@@ -10,7 +10,11 @@ namespace Play.Common.Identity
         {
             return services.ConfigureOptions<ConfigureJwtBearerOptions>()
                     .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
-                    .AddJwtBearer();
+                    .AddJwtBearer(options =>
+        {
+           
+            options.RequireHttpsMetadata = false;
+        });          
         }
     }
-}
\ No newline at end of file
+}
diff --git a/Play.Common/src/Play.Common/MassTransit/Extensions.cs b/Play.Common/src/Play.Common/MassTransit/Extensions.cs
index 33629b9..53b3b94 100644
--- a/Play.Common/src/Play.Common/MassTransit/Extensions.cs
+++ b/Play.Common/src/Play.Common/MassTransit/Extensions.cs
@@ -13,6 +13,30 @@ namespace Play.Common.MassTransit
 {
     public static class Extensions
     {
+        private const string RabbitMq = "RABBITMQ";
+        private const string ServiceBus = "SERVICEBUS";
+
+        public static IServiceCollection AddMassTransitWithMessageBroker(
+            this IServiceCollection services,
+            IConfiguration config,
+            Action<IRetryConfigurator> configureRetries = null)
+        {
+            var serviceSettings = config.GetSection(nameof(ServiceSettings)).Get<ServiceSettings>();
+
+            switch (serviceSettings.MessageBroker?.ToUpper())
+            {
+                case ServiceBus:
+                    services.AddMassTransitWithServiceBus(configureRetries);
+                    break;
+                case RabbitMq:
+                default:
+                    services.AddMassTransitWithRabbitMq(configureRetries);
+                    break;                
+            }
+
+            return services;
+        }
+
         public static IServiceCollection AddMassTransitWithRabbitMq(
             this IServiceCollection services,
             Action<IRetryConfigurator> configureRetries = null)
@@ -28,6 +52,40 @@ namespace Play.Common.MassTransit
             return services;
         }
 
+        public static IServiceCollection AddMassTransitWithServiceBus(
+            this IServiceCollection services,
+            Action<IRetryConfigurator> configureRetries = null)
+        {
+            services.AddMassTransit(configure =>
+            {
+                configure.AddConsumers(Assembly.GetEntryAssembly());
+                configure.UsingPlayEconomyAzureServiceBus(configureRetries);
+            });
+
+            services.AddMassTransitHostedService();
+
+            return services;
+        }        
+
+        public static void UsingPlayEconomyMessageBroker(
+            this IServiceCollectionBusConfigurator configure,
+            IConfiguration config,
+            Action<IRetryConfigurator> configureRetries = null)
+        {
+            var serviceSettings = config.GetSection(nameof(ServiceSettings)).Get<ServiceSettings>();
+
+            switch (serviceSettings.MessageBroker?.ToUpper())
+            {
+                case ServiceBus:
+                    configure.UsingPlayEconomyAzureServiceBus(configureRetries);
+                    break;
+                case RabbitMq:
+                default:
+                    configure.UsingPlayEconomyRabbitMq(configureRetries);
+                    break;                
+            }
+        }
+
         public static void UsingPlayEconomyRabbitMq(
             this IServiceCollectionBusConfigurator configure,
             Action<IRetryConfigurator> configureRetries = null)
@@ -48,5 +106,26 @@ namespace Play.Common.MassTransit
                 configurator.UseMessageRetry(configureRetries);
             });
         }
+
+        public static void UsingPlayEconomyAzureServiceBus(
+            this IServiceCollectionBusConfigurator configure,
+            Action<IRetryConfigurator> configureRetries = null)
+        {
+            configure.UsingAzureServiceBus((context, configurator) =>
+            {
+                var configuration = context.GetService<IConfiguration>();
+                var serviceSettings = configuration.GetSection(nameof(ServiceSettings)).Get<ServiceSettings>();
+                var serviceBusSettings = configuration.GetSection(nameof(ServiceBusSettings)).Get<ServiceBusSettings>();
+                configurator.Host(serviceBusSettings.ConnectionString);
+                configurator.ConfigureEndpoints(context, new KebabCaseEndpointNameFormatter(serviceSettings.ServiceName, false));
+
+                if (configureRetries == null)
+                {
+                    configureRetries = (retryConfigurator) => retryConfigurator.Interval(3, TimeSpan.FromSeconds(5));
+                }
+
+                configurator.UseMessageRetry(configureRetries);
+            });
+        }        
     }
 }
\ No newline at end of file
diff --git a/Play.Common/src/Play.Common/Play.Common.csproj b/Play.Common/src/Play.Common/Play.Common.csproj
index 2e9f83a..707d300 100644
--- a/Play.Common/src/Play.Common/Play.Common.csproj
+++ b/Play.Common/src/Play.Common/Play.Common.csproj
@@ -3,13 +3,16 @@
   <PropertyGroup>
     <TargetFramework>net7.0</TargetFramework>
     <PackageDescription>Common libraries used by Play Economy services.</PackageDescription>
-    <Authors>Thomas Staub</Authors>
+    <Authors>Julio Casal</Authors>
     <Company>.NET Microservices</Company>
   </PropertyGroup>
 
   <ItemGroup>
+    <PackageReference Include="Azure.Extensions.AspNetCore.Configuration.Secrets" Version="1.2.2" />
+    <PackageReference Include="Azure.Identity" Version="1.8.0" />
     <PackageReference Include="MassTransit.AspNetCore" Version="7.3.1" />
     <PackageReference Include="MassTransit.RabbitMQ" Version="7.3.1" />
+    <PackageReference Include="MassTransit.Azure.ServiceBus.Core" Version="7.3.1" />
     <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.0" />
     <PackageReference Include="Microsoft.Extensions.Configuration" Version="7.0.0" />
     <PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="7.0.0" />
diff --git a/Play.Common/src/Play.Common/Settings/MongoDbSettings.cs b/Play.Common/src/Play.Common/Settings/MongoDbSettings.cs
index 8a0be7d..0d1bcf3 100644
--- a/Play.Common/src/Play.Common/Settings/MongoDbSettings.cs
+++ b/Play.Common/src/Play.Common/Settings/MongoDbSettings.cs
@@ -2,10 +2,18 @@ namespace Play.Common.Settings
 {
     public class MongoDbSettings
     {
+        private string connectionString;
+
         public string Host { get; init; }
 
         public int Port { get; init; }
 
-        public string ConnectionString => $"mongodb://{Host}:{Port}";
+        public string ConnectionString
+        {
+            get { return string.IsNullOrWhiteSpace(connectionString) 
+                    ? $"mongodb://{Host}:{Port}" : connectionString; }
+            init { connectionString = value; }
+        }
+
     }
 }
\ No newline at end of file
diff --git a/Play.Common/src/Play.Common/Settings/ServiceBusSettings.cs b/Play.Common/src/Play.Common/Settings/ServiceBusSettings.cs
new file mode 100644
index 0000000..065122a
--- /dev/null
+++ b/Play.Common/src/Play.Common/Settings/ServiceBusSettings.cs
@@ -0,0 +1,7 @@
+namespace Play.Common.Settings
+{
+    public class ServiceBusSettings
+    {
+        public string ConnectionString { get; init; }
+    }
+}
\ No newline at end of file
diff --git a/Play.Common/src/Play.Common/Settings/ServiceSettings.cs b/Play.Common/src/Play.Common/Settings/ServiceSettings.cs
index 046b661..1f2f474 100644
--- a/Play.Common/src/Play.Common/Settings/ServiceSettings.cs
+++ b/Play.Common/src/Play.Common/Settings/ServiceSettings.cs
@@ -4,5 +4,7 @@ namespace Play.Common.Settings
     {
         public string ServiceName { get; init; }
         public string Authority { get; init; }
+        public string MessageBroker { get; init; }
+        public string KeyVaultName { get; init; }
     }
 }
\ No newline at end of file
diff --git a/Play.Common1/.gitignore b/Play.Common1/.gitignore
new file mode 100644
index 0000000..d45db4d
--- /dev/null
+++ b/Play.Common1/.gitignore
@@ -0,0 +1,2 @@
+[Bb]in/
+[Oo]bj/
\ No newline at end of file
diff --git a/Play.Common1/.vscode/tasks.json b/Play.Common1/.vscode/tasks.json
new file mode 100644
index 0000000..35f4315
--- /dev/null
+++ b/Play.Common1/.vscode/tasks.json
@@ -0,0 +1,46 @@
+{
+    "version": "2.0.0",
+    "tasks": [
+        {
+            "label": "build",
+            "command": "dotnet",
+            "type": "process",
+            "args": [
+                "build",
+                "${workspaceFolder}/src/Play.Common/Play.Common.csproj",
+                "/property:GenerateFullPaths=true",
+                "/consoleloggerparameters:NoSummary"
+            ],
+            "problemMatcher": "$msCompile",
+            "group": {
+                "kind": "build",
+                "isDefault": true
+            }
+        },
+        {
+            "label": "publish",
+            "command": "dotnet",
+            "type": "process",
+            "args": [
+                "publish",
+                "${workspaceFolder}/src/Play.Common/Play.Common.csproj",
+                "/property:GenerateFullPaths=true",
+                "/consoleloggerparameters:NoSummary"
+            ],
+            "problemMatcher": "$msCompile"
+        },
+        {
+            "label": "watch",
+            "command": "dotnet",
+            "type": "process",
+            "args": [
+                "watch",
+                "run",
+                "${workspaceFolder}/src/Play.Common/Play.Common.csproj",
+                "/property:GenerateFullPaths=true",
+                "/consoleloggerparameters:NoSummary"
+            ],
+            "problemMatcher": "$msCompile"
+        }
+    ]
+}
\ No newline at end of file
diff --git a/Play.Common1/README.md b/Play.Common1/README.md
new file mode 100644
index 0000000..a4c6b88
--- /dev/null
+++ b/Play.Common1/README.md
@@ -0,0 +1,16 @@
+
+From Root directory
+
+dotnet pack .\Play.Common\src\Play.Common\ --configuration Release -p:PackageVersion=1.0.14  -o .\packages
+
+
+
+
+
+Wechseln ins Verzeichniss packages
+
+dotnet nuget push .\packages\Play.Common.1.0.15.nupkg --source https://git.gibb.ch/api/v4/projects/5940/packages/nuget/index.json --api-key glpat-8GxsWezmB9YrpVnGygyg
+
+
+
+
diff --git a/Play.Common/src/Play.Common/.vs/Play.Common/DesignTimeBuild/.dtbcache.v2 b/Play.Common1/src/Play.Common/.vs/Play.Common/DesignTimeBuild/.dtbcache.v2
similarity index 100%
rename from Play.Common/src/Play.Common/.vs/Play.Common/DesignTimeBuild/.dtbcache.v2
rename to Play.Common1/src/Play.Common/.vs/Play.Common/DesignTimeBuild/.dtbcache.v2
diff --git a/Play.Common/src/Play.Common/.vs/Play.Common/FileContentIndex/55a3eb04-01a5-4be6-9993-d1a5d9968f14.vsidx b/Play.Common1/src/Play.Common/.vs/Play.Common/FileContentIndex/55a3eb04-01a5-4be6-9993-d1a5d9968f14.vsidx
similarity index 100%
rename from Play.Common/src/Play.Common/.vs/Play.Common/FileContentIndex/55a3eb04-01a5-4be6-9993-d1a5d9968f14.vsidx
rename to Play.Common1/src/Play.Common/.vs/Play.Common/FileContentIndex/55a3eb04-01a5-4be6-9993-d1a5d9968f14.vsidx
diff --git a/Play.Common/src/Play.Common/.vs/Play.Common/FileContentIndex/read.lock b/Play.Common1/src/Play.Common/.vs/Play.Common/FileContentIndex/read.lock
similarity index 100%
rename from Play.Common/src/Play.Common/.vs/Play.Common/FileContentIndex/read.lock
rename to Play.Common1/src/Play.Common/.vs/Play.Common/FileContentIndex/read.lock
diff --git a/Play.Common/src/Play.Common/.vs/Play.Common/v17/.futdcache.v2 b/Play.Common1/src/Play.Common/.vs/Play.Common/v17/.futdcache.v2
similarity index 100%
rename from Play.Common/src/Play.Common/.vs/Play.Common/v17/.futdcache.v2
rename to Play.Common1/src/Play.Common/.vs/Play.Common/v17/.futdcache.v2
diff --git a/Play.Common/src/Play.Common/.vs/Play.Common/v17/.suo b/Play.Common1/src/Play.Common/.vs/Play.Common/v17/.suo
similarity index 100%
rename from Play.Common/src/Play.Common/.vs/Play.Common/v17/.suo
rename to Play.Common1/src/Play.Common/.vs/Play.Common/v17/.suo
diff --git a/Play.Common1/src/Play.Common/HealthChecks/Extensions.cs b/Play.Common1/src/Play.Common/HealthChecks/Extensions.cs
new file mode 100644
index 0000000..70be04c
--- /dev/null
+++ b/Play.Common1/src/Play.Common/HealthChecks/Extensions.cs
@@ -0,0 +1,53 @@
+using System;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Diagnostics.HealthChecks;
+using Microsoft.AspNetCore.Routing;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Diagnostics.HealthChecks;
+using MongoDB.Driver;
+using Play.Common.Settings;
+
+namespace Play.Common.HealthChecks
+{
+    public static class Extensions
+    {
+        private const string MongoCheckName = "mongodb";
+        private const string ReadyTagName = "ready";
+        private const string LiveTagName = "live";
+        private const string HealthEndpoint = "health";
+        private const int DefaultSeconds = 3;
+
+        public static IHealthChecksBuilder AddMongoDb(
+            this IHealthChecksBuilder builder,
+            TimeSpan? timeout = default)
+        {
+            return builder.Add(new HealthCheckRegistration(
+                    MongoCheckName,
+                    serviceProvider =>
+                    {
+                        var configuration = serviceProvider.GetService<IConfiguration>();
+                        var mongoDbSettings = configuration.GetSection(nameof(MongoDbSettings))
+                                                           .Get<MongoDbSettings>();
+                        var mongoClient = new MongoClient(mongoDbSettings.ConnectionString);
+                        return new MongoDbHealthCheck(mongoClient);
+                    },
+                    HealthStatus.Unhealthy,
+                    new[] { ReadyTagName },
+                    TimeSpan.FromSeconds(DefaultSeconds)
+                ));
+        }
+
+        public static void MapPlayEconomyHealthChecks(this IEndpointRouteBuilder endpoints)
+        {
+            endpoints.MapHealthChecks($"/{HealthEndpoint}/{ReadyTagName}", new HealthCheckOptions()
+            {
+                Predicate = (check) => check.Tags.Contains(ReadyTagName)
+            });
+            endpoints.MapHealthChecks($"/{HealthEndpoint}/{LiveTagName}", new HealthCheckOptions()
+            {
+                Predicate = (check) => false
+            });
+        }
+    }
+}
\ No newline at end of file
diff --git a/Play.Common1/src/Play.Common/HealthChecks/MongoDbHealthCheck.cs b/Play.Common1/src/Play.Common/HealthChecks/MongoDbHealthCheck.cs
new file mode 100644
index 0000000..481f5af
--- /dev/null
+++ b/Play.Common1/src/Play.Common/HealthChecks/MongoDbHealthCheck.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.Extensions.Diagnostics.HealthChecks;
+using MongoDB.Driver;
+
+namespace Play.Common.HealthChecks
+{
+    public class MongoDbHealthCheck : IHealthCheck
+    {
+        private readonly MongoClient client;
+
+        public MongoDbHealthCheck(MongoClient client)
+        {
+            this.client = client;
+        }
+
+        public async Task<HealthCheckResult> CheckHealthAsync(
+            HealthCheckContext context, 
+            CancellationToken cancellationToken = default)
+        {
+            try
+            {
+                 await client.ListDatabaseNamesAsync(cancellationToken);
+                 return HealthCheckResult.Healthy();
+            }
+            catch (Exception ex)
+            {
+                return HealthCheckResult.Unhealthy(exception: ex);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Play.Common1/src/Play.Common/IEntity.cs b/Play.Common1/src/Play.Common/IEntity.cs
new file mode 100644
index 0000000..b2d0616
--- /dev/null
+++ b/Play.Common1/src/Play.Common/IEntity.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace Play.Common
+{
+    public interface IEntity
+    {
+        Guid Id { get; set; }
+    }
+}
\ No newline at end of file
diff --git a/Play.Common1/src/Play.Common/IRepository.cs b/Play.Common1/src/Play.Common/IRepository.cs
new file mode 100644
index 0000000..8b33b2b
--- /dev/null
+++ b/Play.Common1/src/Play.Common/IRepository.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq.Expressions;
+using System.Threading.Tasks;
+
+namespace Play.Common
+{
+    public interface IRepository<T> where T : IEntity
+    {
+        Task CreateAsync(T entity);
+        Task<IReadOnlyCollection<T>> GetAllAsync();
+        Task<IReadOnlyCollection<T>> GetAllAsync(Expression<Func<T, bool>> filter);
+        Task<T> GetAsync(Guid id);
+        Task<T> GetAsync(Expression<Func<T, bool>> filter);
+        Task RemoveAsync(Guid id);
+        Task UpdateAsync(T entity);
+    }
+}
\ No newline at end of file
diff --git a/Play.Common1/src/Play.Common/Identity/ConfigureJwtBearerOptions.cs b/Play.Common1/src/Play.Common/Identity/ConfigureJwtBearerOptions.cs
new file mode 100644
index 0000000..faddf8a
--- /dev/null
+++ b/Play.Common1/src/Play.Common/Identity/ConfigureJwtBearerOptions.cs
@@ -0,0 +1,62 @@
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Authentication.JwtBearer;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Options;
+using Microsoft.IdentityModel.Tokens;
+using Play.Common.Settings;
+
+namespace Play.Common.Identity
+{
+    public class ConfigureJwtBearerOptions : IConfigureNamedOptions<JwtBearerOptions>
+    {
+        private const string AccessTokenParameter = "access_token";
+        private const string MessageHubPath = "/messageHub";
+
+        private readonly IConfiguration configuration;
+
+        public ConfigureJwtBearerOptions(IConfiguration configuration)
+        {
+            this.configuration = configuration;
+        }
+
+        public void Configure(string name, JwtBearerOptions options)
+        {
+            if (name == JwtBearerDefaults.AuthenticationScheme)
+            {
+                var serviceSettings = configuration.GetSection(nameof(ServiceSettings))
+                                                   .Get<ServiceSettings>();
+
+                options.Authority = serviceSettings.Authority;
+                options.Audience = serviceSettings.ServiceName;
+                options.MapInboundClaims = false;
+                options.TokenValidationParameters = new TokenValidationParameters
+                {
+                    NameClaimType = "name",
+                    RoleClaimType = "role"
+                };
+
+                options.Events = new JwtBearerEvents
+                {
+                    OnMessageReceived = context =>
+                    {
+                        var accessToken = context.Request.Query[AccessTokenParameter];
+                        var path = context.HttpContext.Request.Path;
+
+                        if (!string.IsNullOrEmpty(accessToken) &&
+                            path.StartsWithSegments(MessageHubPath))
+                        {
+                            context.Token = accessToken;
+                        }
+
+                        return Task.CompletedTask;
+                    }
+                };
+            }
+        }
+
+        public void Configure(JwtBearerOptions options)
+        {
+            Configure(Options.DefaultName, options);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Play.Common1/src/Play.Common/Identity/Extensions.cs b/Play.Common1/src/Play.Common/Identity/Extensions.cs
new file mode 100644
index 0000000..86e9936
--- /dev/null
+++ b/Play.Common1/src/Play.Common/Identity/Extensions.cs
@@ -0,0 +1,16 @@
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.AspNetCore.Authentication.JwtBearer;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace Play.Common.Identity
+{
+    public static class Extensions
+    {
+        public static AuthenticationBuilder AddJwtBearerAuthentication(this IServiceCollection services)
+        {
+            return services.ConfigureOptions<ConfigureJwtBearerOptions>()
+                    .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
+                    .AddJwtBearer();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Play.Common1/src/Play.Common/MassTransit/Extensions.cs b/Play.Common1/src/Play.Common/MassTransit/Extensions.cs
new file mode 100644
index 0000000..33629b9
--- /dev/null
+++ b/Play.Common1/src/Play.Common/MassTransit/Extensions.cs
@@ -0,0 +1,52 @@
+using System;
+using System.Reflection;
+using GreenPipes;
+using GreenPipes.Configurators;
+using MassTransit;
+using MassTransit.Definition;
+using MassTransit.ExtensionsDependencyInjectionIntegration;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Play.Common.Settings;
+
+namespace Play.Common.MassTransit
+{
+    public static class Extensions
+    {
+        public static IServiceCollection AddMassTransitWithRabbitMq(
+            this IServiceCollection services,
+            Action<IRetryConfigurator> configureRetries = null)
+        {
+            services.AddMassTransit(configure =>
+            {
+                configure.AddConsumers(Assembly.GetEntryAssembly());
+                configure.UsingPlayEconomyRabbitMq(configureRetries);
+            });
+
+            services.AddMassTransitHostedService();
+
+            return services;
+        }
+
+        public static void UsingPlayEconomyRabbitMq(
+            this IServiceCollectionBusConfigurator configure,
+            Action<IRetryConfigurator> configureRetries = null)
+        {
+            configure.UsingRabbitMq((context, configurator) =>
+            {
+                var configuration = context.GetService<IConfiguration>();
+                var serviceSettings = configuration.GetSection(nameof(ServiceSettings)).Get<ServiceSettings>();
+                var rabbitMQSettings = configuration.GetSection(nameof(RabbitMQSettings)).Get<RabbitMQSettings>();
+                configurator.Host(rabbitMQSettings.Host);
+                configurator.ConfigureEndpoints(context, new KebabCaseEndpointNameFormatter(serviceSettings.ServiceName, false));
+
+                if (configureRetries == null)
+                {
+                    configureRetries = (retryConfigurator) => retryConfigurator.Interval(3, TimeSpan.FromSeconds(5));
+                }
+
+                configurator.UseMessageRetry(configureRetries);
+            });
+        }
+    }
+}
\ No newline at end of file
diff --git a/Play.Common1/src/Play.Common/MongoDB/Extensions.cs b/Play.Common1/src/Play.Common/MongoDB/Extensions.cs
new file mode 100644
index 0000000..aa52bf5
--- /dev/null
+++ b/Play.Common1/src/Play.Common/MongoDB/Extensions.cs
@@ -0,0 +1,42 @@
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using MongoDB.Bson;
+using MongoDB.Bson.Serialization;
+using MongoDB.Bson.Serialization.Serializers;
+using MongoDB.Driver;
+using Play.Common.Settings;
+
+namespace Play.Common.MongoDB
+{
+    public static class Extensions
+    {
+        public static IServiceCollection AddMongo(this IServiceCollection services)
+        {
+            BsonSerializer.RegisterSerializer(new GuidSerializer(BsonType.String));
+            BsonSerializer.RegisterSerializer(new DateTimeOffsetSerializer(BsonType.String));
+
+            services.AddSingleton(serviceProvider =>
+            {
+                var configuration = serviceProvider.GetService<IConfiguration>();
+                var serviceSettings = configuration.GetSection(nameof(ServiceSettings)).Get<ServiceSettings>();
+                var mongoDbSettings = configuration.GetSection(nameof(MongoDbSettings)).Get<MongoDbSettings>();
+                var mongoClient = new MongoClient(mongoDbSettings.ConnectionString);
+                return mongoClient.GetDatabase(serviceSettings.ServiceName);
+            });
+
+            return services;
+        }
+
+        public static IServiceCollection AddMongoRepository<T>(this IServiceCollection services, string collectionName)
+            where T : IEntity
+        {
+            services.AddSingleton<IRepository<T>>(serviceProvider =>
+            {
+                var database = serviceProvider.GetService<IMongoDatabase>();
+                return new MongoRepository<T>(database, collectionName);
+            });
+
+            return services;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Play.Common1/src/Play.Common/MongoDB/MongoRepository.cs b/Play.Common1/src/Play.Common/MongoDB/MongoRepository.cs
new file mode 100644
index 0000000..6e91c2c
--- /dev/null
+++ b/Play.Common1/src/Play.Common/MongoDB/MongoRepository.cs
@@ -0,0 +1,68 @@
+using System;
+using System.Collections.Generic;
+using System.Linq.Expressions;
+using System.Threading.Tasks;
+using MongoDB.Driver;
+
+namespace Play.Common.MongoDB
+{
+
+    public class MongoRepository<T> : IRepository<T> where T : IEntity
+    {
+        private readonly IMongoCollection<T> dbCollection;
+        private readonly FilterDefinitionBuilder<T> filterBuilder = Builders<T>.Filter;
+
+        public MongoRepository(IMongoDatabase database, string collectionName)
+        {
+            dbCollection = database.GetCollection<T>(collectionName);
+        }
+
+        public async Task<IReadOnlyCollection<T>> GetAllAsync()
+        {
+            return await dbCollection.Find(filterBuilder.Empty).ToListAsync();
+        }
+
+        public async Task<IReadOnlyCollection<T>> GetAllAsync(Expression<Func<T, bool>> filter)
+        {
+            return await dbCollection.Find(filter).ToListAsync();
+        }        
+
+        public async Task<T> GetAsync(Guid id)
+        {
+            FilterDefinition<T> filter = filterBuilder.Eq(entity => entity.Id, id);
+            return await dbCollection.Find(filter).FirstOrDefaultAsync();
+        }
+
+        public async Task<T> GetAsync(Expression<Func<T, bool>> filter)
+        {
+            return await dbCollection.Find(filter).FirstOrDefaultAsync();
+        }        
+
+        public async Task CreateAsync(T entity)
+        {
+            if (entity == null)
+            {
+                throw new ArgumentNullException(nameof(entity));
+            }
+
+            await dbCollection.InsertOneAsync(entity);
+        }
+
+        public async Task UpdateAsync(T entity)
+        {
+            if (entity == null)
+            {
+                throw new ArgumentNullException(nameof(entity));
+            }
+
+            FilterDefinition<T> filter = filterBuilder.Eq(existingEntity => existingEntity.Id, entity.Id);
+            await dbCollection.ReplaceOneAsync(filter, entity);
+        }
+
+        public async Task RemoveAsync(Guid id)
+        {
+            FilterDefinition<T> filter = filterBuilder.Eq(entity => entity.Id, id);
+            await dbCollection.DeleteOneAsync(filter);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Play.Common1/src/Play.Common/Play.Common.csproj b/Play.Common1/src/Play.Common/Play.Common.csproj
new file mode 100644
index 0000000..2e9f83a
--- /dev/null
+++ b/Play.Common1/src/Play.Common/Play.Common.csproj
@@ -0,0 +1,20 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net7.0</TargetFramework>
+    <PackageDescription>Common libraries used by Play Economy services.</PackageDescription>
+    <Authors>Thomas Staub</Authors>
+    <Company>.NET Microservices</Company>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="MassTransit.AspNetCore" Version="7.3.1" />
+    <PackageReference Include="MassTransit.RabbitMQ" Version="7.3.1" />
+    <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.0" />
+    <PackageReference Include="Microsoft.Extensions.Configuration" Version="7.0.0" />
+    <PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="7.0.0" />
+    <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
+    <PackageReference Include="MongoDB.Driver" Version="2.18.0" />
+  </ItemGroup>
+
+</Project>
diff --git a/Play.Common/src/Play.Common/Play.Common.sln b/Play.Common1/src/Play.Common/Play.Common.sln
similarity index 100%
rename from Play.Common/src/Play.Common/Play.Common.sln
rename to Play.Common1/src/Play.Common/Play.Common.sln
diff --git a/Play.Common1/src/Play.Common/Settings/MongoDbSettings.cs b/Play.Common1/src/Play.Common/Settings/MongoDbSettings.cs
new file mode 100644
index 0000000..8a0be7d
--- /dev/null
+++ b/Play.Common1/src/Play.Common/Settings/MongoDbSettings.cs
@@ -0,0 +1,11 @@
+namespace Play.Common.Settings
+{
+    public class MongoDbSettings
+    {
+        public string Host { get; init; }
+
+        public int Port { get; init; }
+
+        public string ConnectionString => $"mongodb://{Host}:{Port}";
+    }
+}
\ No newline at end of file
diff --git a/Play.Common1/src/Play.Common/Settings/RabbitMQSettings.cs b/Play.Common1/src/Play.Common/Settings/RabbitMQSettings.cs
new file mode 100644
index 0000000..467fc24
--- /dev/null
+++ b/Play.Common1/src/Play.Common/Settings/RabbitMQSettings.cs
@@ -0,0 +1,7 @@
+namespace Play.Common.Settings
+{
+    public class RabbitMQSettings
+    {
+        public string Host { get; init; }
+    }
+}
\ No newline at end of file
diff --git a/Play.Common1/src/Play.Common/Settings/ServiceBusSettings.cs b/Play.Common1/src/Play.Common/Settings/ServiceBusSettings.cs
new file mode 100644
index 0000000..065122a
--- /dev/null
+++ b/Play.Common1/src/Play.Common/Settings/ServiceBusSettings.cs
@@ -0,0 +1,7 @@
+namespace Play.Common.Settings
+{
+    public class ServiceBusSettings
+    {
+        public string ConnectionString { get; init; }
+    }
+}
\ No newline at end of file
diff --git a/Play.Common1/src/Play.Common/Settings/ServiceSettings.cs b/Play.Common1/src/Play.Common/Settings/ServiceSettings.cs
new file mode 100644
index 0000000..046b661
--- /dev/null
+++ b/Play.Common1/src/Play.Common/Settings/ServiceSettings.cs
@@ -0,0 +1,8 @@
+namespace Play.Common.Settings
+{
+    public class ServiceSettings
+    {
+        public string ServiceName { get; init; }
+        public string Authority { get; init; }
+    }
+}
\ No newline at end of file
diff --git a/Play.Common/src/Play.Common/nuget.config b/Play.Common1/src/Play.Common/nuget.config
similarity index 100%
rename from Play.Common/src/Play.Common/nuget.config
rename to Play.Common1/src/Play.Common/nuget.config
diff --git a/Play.Identity/kubernetes/identity.yaml b/Play.Identity/kubernetes/identity.yaml
new file mode 100644
index 0000000..f0e505b
--- /dev/null
+++ b/Play.Identity/kubernetes/identity.yaml
@@ -0,0 +1,84 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: identity-deployment
+spec:
+  selector:
+    matchLabels:
+      app: identity
+  template:
+    metadata:
+      labels:
+        app: identity
+        azure.workload.identity/use: "true"
+    spec:
+      serviceAccountName: identity-serviceaccount
+      containers:
+        - name: identity
+          image: playeconomy.azurecr.io/play.identity:1.0.10
+          env:
+            - name: ServiceSettings__MessageBroker
+              value: SERVICEBUS
+            - name: ServiceSettings__KeyVaultName
+              value: playeconomy
+            - name: IdentitySettings__PathBase
+              value: /identity-svc
+            - name: IdentitySettings__CertificateCerFilePath
+              value: "/certificates/certificate.crt"
+            - name: IdentitySettings__CertificateKeyFilePath
+              value: "/certificates/certificate.key"
+            - name: IdentityServerSettings__Clients__0__RedirectUris__0
+              value: https://playeconomy.eastus.cloudapp.azure.com/authentication/login-callback
+            - name: IdentityServerSettings__Clients__0__PostLogoutRedirectUris__0
+              value: https://playeconomy.eastus.cloudapp.azure.com/authentication/logout-callback              
+          resources:
+            limits:
+              memory: "128Mi"
+              cpu: "150m"
+          ports:
+            - containerPort: 5002
+          livenessProbe:
+            httpGet:
+              path: /health/live
+              port: 5002
+            initialDelaySeconds: 10
+          readinessProbe:
+            httpGet:
+              path: /health/ready
+              port: 5002
+            initialDelaySeconds: 10
+          volumeMounts:
+            - name: certificate-volume
+              mountPath: /certificates
+      volumes:
+        - name: certificate-volume
+          secret:
+            secretName: signing-cert
+            items:
+              - key: tls.key
+                path: certificate.key
+              - key: tls.crt
+                path: certificate.crt
+
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: identity-service
+spec:
+  type: ClusterIP
+  selector:
+    app: identity
+  ports:
+    - port: 80
+      targetPort: 5002
+
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: identity-serviceaccount
+  annotations:
+    azure.workload.identity/client-id: b68260b6-466a-4483-b432-6df6f7073df1
+  labels:
+    azure.workload.identity/use: "true"
\ No newline at end of file
diff --git a/Play.Identity/kubernetes/singning-cer.yaml b/Play.Identity/kubernetes/singning-cer.yaml
new file mode 100644
index 0000000..99ac088
--- /dev/null
+++ b/Play.Identity/kubernetes/singning-cer.yaml
@@ -0,0 +1,11 @@
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+  name: signing-cert
+spec:
+  secretName: signing-cert
+  issuerRef:
+    name: letsencrypt-prod
+    kind: ClusterIssuer
+  dnsNames:
+    - playeconomy.eastus.cloudapp.azure.com
\ No newline at end of file
diff --git a/Play.Identity/src/Play.Identity.Service/Play.Identity.Service.csproj b/Play.Identity/src/Play.Identity.Service/Play.Identity.Service.csproj
index 187d9c4..bd8aaa3 100644
--- a/Play.Identity/src/Play.Identity.Service/Play.Identity.Service.csproj
+++ b/Play.Identity/src/Play.Identity.Service/Play.Identity.Service.csproj
@@ -11,7 +11,7 @@
     <PackageReference Include="Duende.IdentityServer.AspNetIdentity" Version="6.1.7" />
     <PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="7.0.0" />
     <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="7.0.0" />
-    <PackageReference Include="play.common" Version="1.0.7" />
+    <PackageReference Include="play.common" Version="1.0.16" />
     <PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
   </ItemGroup>
 
diff --git a/Play.Identity/src/Play.Identity.Service/Program.cs b/Play.Identity/src/Play.Identity.Service/Program.cs
index 6360a0d..e1ebc23 100644
--- a/Play.Identity/src/Play.Identity.Service/Program.cs
+++ b/Play.Identity/src/Play.Identity.Service/Program.cs
@@ -12,6 +12,7 @@ using Microsoft.Extensions.DependencyInjection;
 using MongoDB.Bson;
 using MongoDB.Bson.Serialization;
 using MongoDB.Bson.Serialization.Serializers;
+using Play.Common.HealthChecks;
 using Play.Common.MassTransit;
 using Play.Common.Settings;
 using Play.Identity.Service.Entities;
@@ -120,6 +121,9 @@ namespace Play.Identity.Service
                         }
                             });
                         });
+
+                services.AddHealthChecks()
+                    .AddMongoDb();         
         }
 
 
@@ -187,6 +191,7 @@ namespace Play.Identity.Service
             {
                 endpoints.MapControllers();
                 endpoints.MapRazorPages();
+                endpoints.MapPlayEconomyHealthChecks();
             });
         }
     }
diff --git a/Play.Infra/cert-manager/acme-challenge.yaml b/Play.Infra/cert-manager/acme-challenge.yaml
new file mode 100644
index 0000000..b624a3c
--- /dev/null
+++ b/Play.Infra/cert-manager/acme-challenge.yaml
@@ -0,0 +1,21 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: acme-challenge-service
+spec:
+  ports:
+  - port: 80
+    targetPort: 8089
+  selector:
+    acme.cert-manager.io/http01-solver: "true"
+
+---
+apiVersion: getambassador.io/v3alpha1
+kind: Mapping
+metadata:
+  name: acme-challenge-mapping
+spec:
+  hostname: playeconomy.eastus.cloudapp.azure.com
+  prefix: /.well-known/acme-challenge/
+  rewrite: ""
+  service: acme-challenge-service
\ No newline at end of file
diff --git a/Play.Infra/cert-manager/cluster-issuer.yaml b/Play.Infra/cert-manager/cluster-issuer.yaml
new file mode 100644
index 0000000..fb3843e
--- /dev/null
+++ b/Play.Infra/cert-manager/cluster-issuer.yaml
@@ -0,0 +1,14 @@
+apiVersion: cert-manager.io/v1
+kind: ClusterIssuer
+metadata:
+  name: letsencrypt-prod
+spec:
+  acme:
+    server: https://acme-v02.api.letsencrypt.org/directory
+    email: julioc@dotnetmicroservices.com
+    privateKeySecretRef:
+      name: letsencrypt-prod
+    solvers:
+      - http01:
+          ingress:
+            class: nginx
\ No newline at end of file
diff --git a/Play.Infra/emissary-ingress/host.yaml b/Play.Infra/emissary-ingress/host.yaml
new file mode 100644
index 0000000..9c5e477
--- /dev/null
+++ b/Play.Infra/emissary-ingress/host.yaml
@@ -0,0 +1,10 @@
+apiVersion: getambassador.io/v3alpha1
+kind: Host
+metadata:
+  name: playeconomy-host
+spec:
+  hostname: playeconomy.eastus.cloudapp.azure.com
+  acmeProvider:
+    email: julioc@dotnetmicroservices.com
+  tlsSecret:
+    name: playeconomy-tls
\ No newline at end of file
diff --git a/Play.Infra/emissary-ingress/listener.yaml b/Play.Infra/emissary-ingress/listener.yaml
new file mode 100644
index 0000000..30a2c6d
--- /dev/null
+++ b/Play.Infra/emissary-ingress/listener.yaml
@@ -0,0 +1,24 @@
+apiVersion: getambassador.io/v3alpha1
+kind: Listener
+metadata:
+  name: http-listener
+spec:   
+  port: 8080
+  protocol: HTTP
+  securityModel: XFP # X-Forwarded-Proto 
+  hostBinding:  
+    namespace:
+      from: SELF
+
+---
+apiVersion: getambassador.io/v3alpha1
+kind: Listener
+metadata:
+  name: https-listener
+spec:   
+  port: 8443
+  protocol: HTTPS
+  securityModel: XFP
+  hostBinding:  
+    namespace:
+      from: SELF
\ No newline at end of file
diff --git a/Play.Infra/emissary-ingress/mappings.yaml b/Play.Infra/emissary-ingress/mappings.yaml
new file mode 100644
index 0000000..3c9411c
--- /dev/null
+++ b/Play.Infra/emissary-ingress/mappings.yaml
@@ -0,0 +1,50 @@
+apiVersion: getambassador.io/v3alpha1
+kind: Mapping
+metadata:
+  name: identity-mapping
+spec:
+  hostname: playeconomy.eastus.cloudapp.azure.com
+  prefix: /identity-svc/
+  service: identity-service.identity
+
+---
+apiVersion: getambassador.io/v3alpha1
+kind: Mapping
+metadata:
+  name: catalog-mapping
+spec:
+  hostname: playeconomy.eastus.cloudapp.azure.com
+  prefix: /catalog-svc/
+  service: catalog-service.catalog
+
+---
+apiVersion: getambassador.io/v3alpha1
+kind: Mapping
+metadata:
+  name: inventory-mapping
+spec:
+  hostname: playeconomy.eastus.cloudapp.azure.com
+  prefix: /inventory-svc/
+  service: inventory-service.inventory
+
+---
+apiVersion: getambassador.io/v3alpha1
+kind: Mapping
+metadata:
+  name: trading-mapping
+spec:
+  hostname: playeconomy.eastus.cloudapp.azure.com
+  prefix: /trading-svc/
+  service: trading-service.trading
+  allow_upgrade:
+    - websocket
+
+---
+apiVersion: getambassador.io/v3alpha1
+kind: Mapping
+metadata:
+  name: frontend-mapping
+spec:
+  hostname: playeconomy.eastus.cloudapp.azure.com
+  prefix: /
+  service: frontend-client.frontend
diff --git a/Play.Infra/emissary-ingress/tls-certificate.yaml b/Play.Infra/emissary-ingress/tls-certificate.yaml
new file mode 100644
index 0000000..d45492d
--- /dev/null
+++ b/Play.Infra/emissary-ingress/tls-certificate.yaml
@@ -0,0 +1,11 @@
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+  name: playeconomy-tls-cert
+spec:
+  secretName: playeconomy-tls
+  issuerRef:
+    name: letsencrypt-prod
+    kind: ClusterIssuer
+  dnsNames:
+    - "playeconomy.eastus.cloudapp.azure.com"
\ No newline at end of file
diff --git a/Play.Inventory/src/Play.Inventory.Service/Play.Inventory.Service.csproj b/Play.Inventory/src/Play.Inventory.Service/Play.Inventory.Service.csproj
index 45f4b3d..028c72d 100644
--- a/Play.Inventory/src/Play.Inventory.Service/Play.Inventory.Service.csproj
+++ b/Play.Inventory/src/Play.Inventory.Service/Play.Inventory.Service.csproj
@@ -7,7 +7,7 @@
   <ItemGroup>
     <PackageReference Include="Microsoft.Extensions.Http.Polly" Version="7.0.0" />
     <PackageReference Include="Play.Catalog.Contracts" Version="1.0.1" />
-    <PackageReference Include="Play.Common" Version="1.0.13" />
+    <PackageReference Include="Play.Common" Version="1.0.16" />
     <PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
   </ItemGroup>
 
diff --git a/Play.Trading/src/Play.Trading.Service/Play.Trading.Service.csproj b/Play.Trading/src/Play.Trading.Service/Play.Trading.Service.csproj
index 82df04a..cd621ae 100644
--- a/Play.Trading/src/Play.Trading.Service/Play.Trading.Service.csproj
+++ b/Play.Trading/src/Play.Trading.Service/Play.Trading.Service.csproj
@@ -7,7 +7,7 @@
   <ItemGroup>
     <PackageReference Include="MassTransit.MongoDB" Version="7.3.1" />
     <PackageReference Include="Play.Catalog.Contracts" Version="1.0.1" />
-    <PackageReference Include="Play.Common" Version="1.0.13" />
+    <PackageReference Include="Play.Common" Version="1.0.16" />
     <PackageReference Include="Play.Identity.Contracts" Version="1.0.1" />
     <PackageReference Include="Play.Inventory.Contracts" Version="1.0.1" />
     <PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
diff --git a/README.md b/README.md
index 557e5e5..4c88669 100644
--- a/README.md
+++ b/README.md
@@ -4,4 +4,17 @@ Login: admin@play.com
 PW: Pass@word1
 
 
-https://learn.dotnetacademy.io/enrollments
\ No newline at end of file
+https://learn.dotnetacademy.io/enrollments
+
+
+| Microservice | Port http |Port https|
+|--|--|--|
+|Catalog  | 5000 |5001|
+|Inventory  |5004  |5005|
+|Trading  | 5006 |5007|
+|Frontend | 3000 ||
+|Frontendv2| 5008  |5009|
+|Identity| 5002  |5003|
+|Mongo  | 27017  ||
+|rabbistmq|  5672 /   15672 ||
+
diff --git a/packages/Play.Common.1.0.15.nupkg b/packages/Play.Common.1.0.15.nupkg
new file mode 100644
index 0000000000000000000000000000000000000000..105adc0b1e54bb8ad029fe538688920edaf56aec
GIT binary patch
literal 14224
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
WvK%zbKU+ZmeS`jH>Y4MOum1&3VNF>8

literal 0
HcmV?d00001

diff --git a/packages/Play.Common.1.0.16.nupkg b/packages/Play.Common.1.0.16.nupkg
new file mode 100644
index 0000000000000000000000000000000000000000..8ca039a7ccf46f90deab390734a3be99ab782cdc
GIT binary patch
literal 14224
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
b_WwgtD9b^^{AUX2e<kQ&q+U4w^YniK!kb%l

literal 0
HcmV?d00001

-- 
GitLab