diff --git a/.grenrc.json b/.grenrc.json index b6f88e81c..8c0969f47 100644 --- a/.grenrc.json +++ b/.grenrc.json @@ -9,4 +9,4 @@ "Bug Fixes:": ["bug"] }, "changelogFilename": "CHANGELOG.md" -} \ No newline at end of file +} diff --git a/Dockerfile b/Dockerfile index 51fbb9f5b..ca55424af 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM microsoft/dotnet:2.1-sdk AS build-env +FROM microsoft/dotnet:2.2-sdk AS build-env ARG PROJECT_NAME=decrypt-api @@ -15,10 +15,10 @@ COPY ./src/key-managment ./key-managment RUN dotnet publish $PROJECT_NAME/$PROJECT_NAME.csproj -c Release -o ./obj/Docker/publish # Build runtime image -FROM microsoft/dotnet:2.1.6-aspnetcore-runtime as release +FROM microsoft/dotnet:2.2.1-aspnetcore-runtime-alpine as release ARG PROJECT_NAME=decrypt-api ENV PROJECT_NAME_ENV=$PROJECT_NAME -RUN groupadd -r dotnet && useradd --no-log-init -r -g dotnet -d /home/dotnet -ms /bin/bash dotnet +RUN addgroup dotnet && adduser -D -G dotnet -h /home/dotnet dotnet USER dotnet WORKDIR /home/dotnet/app ENV ASPNETCORE_URLS=http://+:9999 diff --git a/example/deployment-kamus/configmap.yaml b/example/deployment-kamus/configmap.yaml index cd451ab20..c3d741687 100644 --- a/example/deployment-kamus/configmap.yaml +++ b/example/deployment-kamus/configmap.yaml @@ -3,4 +3,4 @@ kind: ConfigMap metadata: name: encrypted-secrets-cm data: - key: 4AD7lM6lc4dGvE3oF+5w8g==:WrcckiNNOAlMhuWHaM0kTw== \ No newline at end of file + token: ezBR+Ew+Itwg6fA/tQjxzg==:/DH+kSV3UN8eRUxT/cJp5w== \ No newline at end of file diff --git a/kamus.sln b/kamus.sln index 11f9a78e4..30c777293 100644 --- a/kamus.sln +++ b/kamus.sln @@ -16,6 +16,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "decrypt-api", "src\decrypt- EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "encrypt-api", "src\encrypt-api\encrypt-api.csproj", "{E69C788D-77EC-4C83-842A-425978A715FD}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "crd-controller", "src\crd\crd-controller.csproj", "{92192778-DE65-4517-BEB0-12FEC097927C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -122,6 +124,18 @@ Global {E69C788D-77EC-4C83-842A-425978A715FD}.Release|x64.Build.0 = Release|Any CPU {E69C788D-77EC-4C83-842A-425978A715FD}.Release|x86.ActiveCfg = Release|Any CPU {E69C788D-77EC-4C83-842A-425978A715FD}.Release|x86.Build.0 = Release|Any CPU + {92192778-DE65-4517-BEB0-12FEC097927C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {92192778-DE65-4517-BEB0-12FEC097927C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {92192778-DE65-4517-BEB0-12FEC097927C}.Debug|x64.ActiveCfg = Debug|Any CPU + {92192778-DE65-4517-BEB0-12FEC097927C}.Debug|x64.Build.0 = Debug|Any CPU + {92192778-DE65-4517-BEB0-12FEC097927C}.Debug|x86.ActiveCfg = Debug|Any CPU + {92192778-DE65-4517-BEB0-12FEC097927C}.Debug|x86.Build.0 = Debug|Any CPU + {92192778-DE65-4517-BEB0-12FEC097927C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {92192778-DE65-4517-BEB0-12FEC097927C}.Release|Any CPU.Build.0 = Release|Any CPU + {92192778-DE65-4517-BEB0-12FEC097927C}.Release|x64.ActiveCfg = Release|Any CPU + {92192778-DE65-4517-BEB0-12FEC097927C}.Release|x64.Build.0 = Release|Any CPU + {92192778-DE65-4517-BEB0-12FEC097927C}.Release|x86.ActiveCfg = Release|Any CPU + {92192778-DE65-4517-BEB0-12FEC097927C}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/crd-controller/Program.cs b/src/crd-controller/Program.cs new file mode 100644 index 000000000..cfd68ed6c --- /dev/null +++ b/src/crd-controller/Program.cs @@ -0,0 +1,118 @@ +using System; +using System.Collections.ObjectModel; +using System.Threading.Tasks; +using System.Linq; +using k8s; +using System.Reactive.Linq; +using System.IO; +using Microsoft.AspNetCore.JsonPatch; +using k8s.Models; +using System.Collections.Generic; +using Polly; +using Newtonsoft.Json.Linq; +using Kamus.KeyManagement; + +namespace crd_controller +{ + class KamusSecret : KubernetesObject + { + public Dictionary Data { get; set; } + public string Type { get; set; } + public V1ObjectMeta Metadata { get; set; } + } + + class Program + { + public static SymmetricKeyManagement mKeyManagement { get; private set; } + + static void Main(string[] args) + { + var configuration = KubernetesClientConfiguration.BuildConfigFromConfigFile(); + var kubernetes = new Kubernetes(configuration); + + mKeyManagement = new SymmetricKeyManagement("rWnWbaFutavdoeqUiVYMNJGvmjQh31qaIej/vAxJ9G0="); + + Console.WriteLine("hello"); + + var blah = Observable.FromAsync(async () => + { + var result = await kubernetes.ListClusterCustomObjectWithHttpMessagesAsync("soluto.com", "v1alpha1", "kamussecrets", watch: true); + var subject = new System.Reactive.Subjects.Subject<(WatchEventType, KamusSecret)>(); + + var watcher = result.Watch( + onEvent: (@type, @event) => subject.OnNext((@type, @event)), + onError: e => subject.OnError(e), + onClosed: () => subject.OnCompleted()); + return subject; + }) + .SelectMany(x => x) + .Select(t => (t.Item1, t.Item2 as KamusSecret)) + .Where(t => t.Item2 != null) + .SelectMany(x => + Observable.FromAsync(async () => await HandleEvent(x.Item1, x.Item2, kubernetes)) + ) + .Subscribe(onNext: t => { Console.WriteLine(t); }, onError: e => { Console.WriteLine(e); }, onCompleted: () => { Console.WriteLine("done!"); }); + + Console.ReadKey(); + + Console.WriteLine("helo"); + + } + + private static async Task HandleEvent(WatchEventType @event, KamusSecret kamusSecret, Kubernetes kubernetes) + { + switch (@event) + { + case WatchEventType.Added: + await HandleAdd(kamusSecret, kubernetes); + return; + + case WatchEventType.Deleted: + await HandleDelete(kamusSecret, kubernetes); + return; + + default: + Console.WriteLine($"Event {@event} is not supported yet"); + return; + + } + } + + private static async Task HandleAdd(KamusSecret kamusSecret, Kubernetes kubernetes) + { + var @namespace = kamusSecret.Metadata.NamespaceProperty ?? "default"; + var serviceAccount = "default"; + var id = $"{@namespace}:{serviceAccount}"; + + var decryptedItems = new Dictionary(); + + foreach(var item in kamusSecret.Data) + { + var decrypted = await mKeyManagement.Decrypt(item.Value, id); + + decryptedItems.Add(item.Key, decrypted); + } + + + var secret = new V1Secret + { + Metadata = new V1ObjectMeta + { + Name = kamusSecret.Metadata.Name, + NamespaceProperty = @namespace + }, + Type = kamusSecret.Type, + StringData = decryptedItems + }; + + await kubernetes.CreateNamespacedSecretAsync(secret, @namespace); + } + + private static async Task HandleDelete(KamusSecret kamusSecret, Kubernetes kubernetes) + { + var @namespace = kamusSecret.Metadata.NamespaceProperty ?? "default"; + + await kubernetes.DeleteNamespacedSecretAsync(new V1DeleteOptions { }, kamusSecret.Metadata.Name, @namespace); + } + } +} diff --git a/src/crd-controller/crd-controller.csproj b/src/crd-controller/crd-controller.csproj new file mode 100644 index 000000000..d48b3b65f --- /dev/null +++ b/src/crd-controller/crd-controller.csproj @@ -0,0 +1,29 @@ + + + + Exe + netcoreapp2.2 + + + + 7.3 + + + 7.3 + + + + + + + + + + + + + + + + + diff --git a/src/crd-controller/crd.yaml b/src/crd-controller/crd.yaml new file mode 100644 index 000000000..77bf248bc --- /dev/null +++ b/src/crd-controller/crd.yaml @@ -0,0 +1,22 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + # name must match the spec fields below, and be in the form: . + name: kamussecrets.soluto.com +spec: + # group name to use for REST API: /apis// + group: soluto.com + # version name to use for REST API: /apis// + version: v1alpha1 + # either Namespaced or Cluster + scope: Namespaced + names: + # plural name to be used in the URL: /apis/// + plural: kamussecrets + # singular name to be used as an alias on the CLI and for display + singular: kamussecret + # kind is normally the CamelCased singular type. Your resource manifests use this. + kind: KamusSecret + # shortNames allow shorter string to match your resource on the CLI + shortNames: + - ks \ No newline at end of file diff --git a/src/crd-controller/tls.yaml b/src/crd-controller/tls.yaml new file mode 100644 index 000000000..6dfba7d04 --- /dev/null +++ b/src/crd-controller/tls.yaml @@ -0,0 +1,7 @@ +apiVersion: "soluto.com/v1alpha1" +kind: KamusSecret +metadata: + name: my-tls-secret +type: TlsSecret +data: + key: J9NYLzTC/O44DvlCEZ+LfQ==:Cc9O5zQzFOyxwTD5ZHseqg== \ No newline at end of file diff --git a/src/decrypt-api/decrypt-api.csproj b/src/decrypt-api/decrypt-api.csproj index 23b128277..7b0eeb023 100644 --- a/src/decrypt-api/decrypt-api.csproj +++ b/src/decrypt-api/decrypt-api.csproj @@ -1,9 +1,9 @@  - netcoreapp2.1 + netcoreapp2.2 - 0.1.1.0 + 0.1.2.0 @@ -17,7 +17,7 @@ - + @@ -25,7 +25,7 @@ - + diff --git a/src/encrypt-api/encrypt-api.csproj b/src/encrypt-api/encrypt-api.csproj index 3e9ddf5d8..efaaa0e7e 100644 --- a/src/encrypt-api/encrypt-api.csproj +++ b/src/encrypt-api/encrypt-api.csproj @@ -1,9 +1,9 @@  - netcoreapp2.1 + netcoreapp2.2 - 0.1.1.0 + 0.1.2.0 @@ -16,15 +16,16 @@ - + - + - + + diff --git a/src/key-managment/key-managment.csproj b/src/key-managment/key-managment.csproj index 2ad6f9588..438d97cfd 100644 --- a/src/key-managment/key-managment.csproj +++ b/src/key-managment/key-managment.csproj @@ -6,11 +6,11 @@ - - - - - + + + + + diff --git a/tests/integration/integration.csproj b/tests/integration/integration.csproj index 3aaa89cb2..3620486e7 100644 --- a/tests/integration/integration.csproj +++ b/tests/integration/integration.csproj @@ -7,8 +7,8 @@ - - + +