mumoshu / aws-secret-operator Goto Github PK
View Code? Open in Web Editor NEWA Kubernetes operator that automatically creates and updates Kubernetes secrets according to what are stored in AWS Secrets Manager.
License: Apache License 2.0
A Kubernetes operator that automatically creates and updates Kubernetes secrets according to what are stored in AWS Secrets Manager.
License: Apache License 2.0
Hi there
Thank you for your awesome work on this project. As this project is written in Golang, do you have any plan to support building multi-arch images? If yes, I think I can contribute to this feature
AWS recently added the capability to increase throughput for SSM parameter store:
https://docs.aws.amazon.com/systems-manager/latest/userguide/parameter-store-throughput.html
Is there a chance aws-secret-operator
could be updated to support it?
make
go build -o bin/aws-secret-operator ./cmd/manager
go: github.com/operator-framework/[email protected]: invalid pseudo-version: revision is shorter than canonical (e429e79f9a6a)
go version
go version go1.14 darwin/amd64
Hi,
aws-secret-operator deployed from the helm chart does not have the recent CRD.
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
aws-secret-operator test 1 2022-08-26 14:35:41.937816 +0200 CEST deployed aws-secret-operator-0.2.3 0.5.2
when I try to apply the AWSSecret definition and create labels on the secret I get an error:
---
apiVersion: mumoshu.github.io/v1alpha1
kind: AWSSecret
metadata:
name: aws-secret1
labels:
app_name: test-app1
annotations:
app_name: test1
spec:
type: Opaque
metadata:
labels:
app_name: test-app1
stringDataFrom:
secretsManagerSecretRef:
secretId: Secret
versionId: xxxx
$ k apply -f awssecret.yaml
error: error validating "awssecret.yaml": error validating data: ValidationError(AWSSecret.spec): unknown field "metadata" in io.github.mumoshu.v1alpha1.AWSSecret.spec; if you choose to ignore these errors, turn validation off with --validate=false
It looks like the CRD installed via helm chart has an old CRD version which doesn't support the spec.metadata.labels/annotations
kg crd awssecrets.mumoshu.github.io -oyaml
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
creationTimestamp: "2022-08-26T12:35:38Z"
generation: 1
name: awssecrets.mumoshu.github.io
resourceVersion: "425710227"
uid: e1fbb32e-8ba5-4588-b04e-0476eabd3d09
spec:
conversion:
strategy: None
group: mumoshu.github.io
names:
kind: AWSSecret
listKind: AWSSecretList
plural: awssecrets
singular: awssecret
scope: Namespaced
versions:
- name: v1alpha1
schema:
openAPIV3Schema:
description: AWSSecret is the Schema for the awssecrets API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: AWSSecretSpec defines the desired state of AWSSecret
properties:
dataFrom:
description: DataFrom data field is used to store arbitrary data,
encoded using base64.
properties:
secretsManagerSecretRef:
description: SecretsManagerSecretRef defines from which SecretsManager
Secret the Kubernetes secret is built See https://docs.aws.amazon.com/secretsmanager/latest/userguide/terms-concepts.html
for the concepts
properties:
secretId:
description: SecretId is the SecretId a.k.a `--secret-id`
of the SecretsManager secret version
type: string
versionId:
description: VersionIdis the VersionId a.k.a `--version-id`
of the SecretsManager secret version
type: string
type: object
type: object
stringDataFrom:
description: StringDataFrom stringData field is provided for convenience,
and allows you to provide secret data as unencoded strings.
properties:
secretsManagerSecretRef:
description: SecretsManagerSecretRef defines from which SecretsManager
Secret the Kubernetes secret is built See https://docs.aws.amazon.com/secretsmanager/latest/userguide/terms-concepts.html
for the concepts
properties:
secretId:
description: SecretId is the SecretId a.k.a `--secret-id`
of the SecretsManager secret version
type: string
versionId:
description: VersionIdis the VersionId a.k.a `--version-id`
of the SecretsManager secret version
type: string
type: object
type: object
type:
description: Used to facilitate programmatic handling of secret data.
type: string
type: object
status:
description: AWSSecretStatus defines the observed state of AWSSecret
type: object
type: object
served: true
storage: true
status:
acceptedNames:
kind: AWSSecret
listKind: AWSSecretList
plural: awssecrets
singular: awssecret
conditions:
- lastTransitionTime: "2022-08-26T12:35:38Z"
message: no conflicts found
reason: NoConflicts
status: "True"
type: NamesAccepted
- lastTransitionTime: "2022-08-26T12:35:38Z"
message: the initial names have been accepted
reason: InitialNamesAccepted
status: "True"
type: Established
storedVersions:
- v1alpha1
I've updated manually the CRD
k apply -f https://raw.githubusercontent.com/mumoshu/aws-secret-operator/3d4b7715d7eb7a37ed0c03d610064dd942a34576/deploy/crds/mumoshu.github.io_awssecrets.yaml
customresourcedefinition.apiextensions.k8s.io/awssecrets.mumoshu.github.io configured
and it looks good now
k apply -f awssecret.yaml
awssecret.mumoshu.github.io/aws-secret1 configured
kg secret aws-secret1 -o yaml
apiVersion: v1
data:
AWSVersionId: xxxxx
password: xxxxx
username: xxxx
kind: Secret
metadata:
labels:
app_name: test-app1
name: aws-secret1
namespace: test
.
.
.
.
type: Opaque
It would be nice to fix the crd in the helm chart ;)
Also - documentation says about the https://github.com/mumoshu/aws-secret-operator#advanced-configuration to set the
spec.labels
/ spec.annotations
but it should be spec.metadata.labels
/ spec.metadata.annotations
Can we avoid each secret being created to include the key for AWSVersionID
?
We have a CRD that can only accept a single Key/Value and it is currently not compatible with AWSSecret CRD's
Please help to see how to support automatic update of password of aws secretsmanager, and identify the VersionStages: AWSCURRENT field, which can automatically obtain the latest Versionid without manual configuration
All previous versions supported these features (image: 3onaco/aws-secret-operator:0.2.4 )eks Version:"v1.19.15-eks"
Now the latest version does not support it, can you help to support automatic update of password of aws secretsmanager,?(image: image mumoshu/aws-secret-operator:0.4.0)eks GitVersion:"v1.22.5"
apiVersion: mumoshu.github.io/v1alpha1
kind: AWSSecret
metadata:
name: AWSSecretPrd
namespace: prd
spec:
stringDataFrom:
secretsManagerSecretRef:
VersionStages: AWSCURRENT
secretId: vdev/eks/n8n/app-credentials
thanks
Hi, @mumoshu
Recently, EKS v1.22 has been released.
The CustomResourceDefinition
API version apiextensions.k8s.io/v1beta1
was removed in Kubernetes 1.22.
aws-secrets-operator
's CRD seems to be apiextensions.k8s.io/v1beta1
.
Because of this, I think I cannot deploy aws-secrets-opertator
in Kubernetes 1.22.
API version v1 custom resource definitions are required to have Open API v3 schema validation defined.
Upgrading to v1 seems like a lot of work, can you address it?
Would it make sense to watch the SecretsManager for version changes?
Hey there,
Is there any possibility to integrate this AWS ACM to retrieve ACM as secrets? I'm asking because a CERTs can be stored as secrets...
thank you
Marcello
When an AWS secret is stored as non-JSON plaintext rather than key value pairs, the operator fails to map secret to a Kubernetes secret object.
Desired behavior would be to store the secret blob in a single key value pair in a Kubernetes secret with a key name something like "secretString"
Error message:
{
"level": "error",
"ts": 1549493879.5115652,
"logger": "kubebuilder.controller",
"caller": "controller/controller.go:209",
"msg": "Reconciler error",
"Controller": "awssecret-controller",
"Request": "default/test-secret",
"error": "failed to compute secret for cr: failed to get json secret as map: invalid character 'a' looking for beginning of value",
"errorVerbose": "invalid character 'a' looking for beginning of value
failed to get json secret as map
github.com/mumoshu/aws-secret-operator/pkg/controller/awssecret.(*ReconcileAWSSecret).newSecretForCR
/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/pkg/controller/awssecret/awssecret_controller.go:154
github.com/mumoshu/aws-secret-operator/pkg/controller/awssecret.(*ReconcileAWSSecret).Reconcile
/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/pkg/controller/awssecret/awssecret_controller.go:107
github.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem
/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:207
github.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func1
/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:157
github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait.JitterUntil.func1
/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:133
github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait.JitterUntil
/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:134
github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait.Until
/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:88
runtime.goexit
/usr/local/Cellar/go/1.11/libexec/src/runtime/asm_amd64.s:1333
failed to compute secret for cr
github.com/mumoshu/aws-secret-operator/pkg/controller/awssecret.(*ReconcileAWSSecret).Reconcile
/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/pkg/controller/awssecret/awssecret_controller.go:109
github.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem
/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:207
github.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func1
/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:157
github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait.JitterUntil.func1
/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:133
github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait.JitterUntil
/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:134
github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait.Until
/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:88
runtime.goexit
/usr/local/Cellar/go/1.11/libexec/src/runtime/asm_amd64.s:1333",
"stacktrace": "github.com/mumoshu/aws-secret-operator/vendor/github.com/go-logr/zapr.(*zapLogger).Error
/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/github.com/go-logr/zapr/zapr.go:128
github.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem
/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:209
github.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func1
/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:157
github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait.JitterUntil.func1
/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:133
github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait.JitterUntil
/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:134
github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait.Until
/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:88"
}
Hi,
I hope I haven't missed something in the docs or example.
I have the secrets operator deployed in a aws-secrets-operator
namespace, configured to watch all namespaces with a ClusterRole to allow it to do so.
Upon creating an AWSSecret resource in a different namespace, the secret is created in the namespace where the operator is deployed. I would have expected for the secret to be created in the namespace I created the AWSSecret in.
Have I misunderstood something, or perhaps misconfigured?
Thanks
Hi,
Can you add license for this project?
Nice effort!!
Thanks,
The README says "Note that aws-secret-operator intentionally disallow omitting VersionId". However, if one creates a manifest with no VersionId, it is accepted. The resulting behavior is that the secret is updated at every poll cycle.
I followed the instructions to install the operator in my own minikube instance.
However the operator fail when i try to create a secret with the following log
How can i pass AWS credentials to the operator? IAM Roles?
{"level":"error","ts":1553702614.8361397,"logger":"kubebuilder.controller","caller":"controller/controller.go:209","msg":"Reconciler error","Controller":"awssecret-controller","Request":"default/example.alessandro.hbc.com","error":"failed to compute secret for cr: failed to get json secret as map: NoCredentialProviders: no valid providers in chain. Deprecated.\n\tFor verbose messaging see aws.Config.CredentialsChainVerboseErrors","errorVerbose":"NoCredentialProviders: no valid providers in chain. Deprecated.\n\tFor verbose messaging see aws.Config.CredentialsChainVerboseErrors\nfailed to get json secret as map\ngithub.com/mumoshu/aws-secret-operator/pkg/controller/awssecret.(*ReconcileAWSSecret).newSecretForCR\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/pkg/controller/awssecret/awssecret_controller.go:154\ngithub.com/mumoshu/aws-secret-operator/pkg/controller/awssecret.(*ReconcileAWSSecret).Reconcile\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/pkg/controller/awssecret/awssecret_controller.go:107\ngithub.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:207\ngithub.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func1\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:157\ngithub.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait.JitterUntil.func1\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:133\ngithub.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait.JitterUntil\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:134\ngithub.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait.Until\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:88\nruntime.goexit\n\t/usr/local/Cellar/go/1.11/libexec/src/runtime/asm_amd64.s:1333\nfailed to compute secret for cr\ngithub.com/mumoshu/aws-secret-operator/pkg/controller/awssecret.(*ReconcileAWSSecret).Reconcile\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/pkg/controller/awssecret/awssecret_controller.go:109\ngithub.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:207\ngithub.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func1\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:157\ngithub.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait.JitterUntil.func1\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:133\ngithub.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait.JitterUntil\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:134\ngithub.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait.Until\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:88\nruntime.goexit\n\t/usr/local/Cellar/go/1.11/libexec/src/runtime/asm_amd64.s:1333","stacktrace":"github.com/mumoshu/aws-secret-operator/vendor/github.com/go-logr/zapr.(*zapLogger).Error\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/github.com/go-logr/zapr/zapr.go:128\ngithub.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:209\ngithub.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func1\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:157\ngithub.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait.JitterUntil.func1\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:133\ngithub.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait.JitterUntil\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:134\ngithub.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait.Until\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:88"}
Hi
Is it possible to use IAM role for AWS Secret Operator. Tried it but could not get it working. Perhaps the AWS SDK in use is not recent enough?
https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html
Kind regards,
Tommi Laukkanen
Hi! I've been using your operator (which is great and very useful) version 0.3.3
and after change to 0.4.0
seems that it has stopped working both for stringDataFrom
and dataFrom
options. Latest version has support for base64 secrets (#43) which I'd like to use.
Steps to reproduce (example for stringDataFrom
option):
debug-secret
with Secret Key: key
and Secret Value: value
apiVersion: mumoshu.github.io/v1alpha1
kind: AWSSecret
metadata:
name: debug-secret
spec:
stringDataFrom:
secretsManagerSecretRef:
secretId: debug-secret
debug-secret
with empty data field (I've deleted irrelevant lines):kind: Secret
apiVersion: v1
metadata:
name: debug-secret
namespace: debug
type: Opaque
data: {}
operator logs
{"level":"info","ts":1624874936.1018052,"logger":"controller_awssecret","msg":"Secret does not exist, Creating a new Secret","Request.Namespace":"debug","Request.Name":"debug-secret","desired.Namespace":"debug","desired.Name":"debug-secret"}
{"level":"info","ts":1624874936.1154666,"logger":"controller_awssecret","msg":"Secret Created successfully, RequeueAfter 5 minutes","Request.Namespace":"debug","Request.Name":"debug-secret"}
I would be grateful for help
Version 0.2.4 fails to convert an AWS secret to a Kubernetes secret if the value is multi-line:
$ aws secretsmanager put-secret-value --secret-id example \
--secret-string '{"example.txt": "example
multiline"}'
$ aws secretsmanager get-secret-value --secret-id example | \
grep Secret
"SecretString": "{\"example.txt\": \"example\nmultiline\"}",
AWS has no problem with it. Alternately, I tried
$ aws secretsmanager put-secret-value --secret-id example \
--secret-string '{"example.txt": "example\nmultiline"}'
$ aws secretsmanager get-secret-value --secret-id example | \
grep Secret
"SecretString": "{\"example.txt\": \"example\\nmultiline\"}",
Either way, aws-secret-operator
fails with
"error": "failed to compute secret for cr: failed to get json secret as map: invalid character \n in string literal"
One of the reasons to use Secrets rather than ParameterStore is that Secrets can hold big values, like TLS certificate chains. I want aws-secret-operator
to support that.
First off -- awesome project! I was looking at the role permissions and this thing has a lot :) if I understand correctly, only access to secrets is required given the CRD does not change pods/replicasets/statefulsets/etc -- is that correct?
I installed according to Installation in README.md
.
But Pod was created instead of Secret.
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
aws-secret-operator-8446b99787-9hw8z 1/1 Running 0 1m
example-pod 1/1 Running 0 8s
$ kubectl get secrets
NAME TYPE DATA AGE
aws-secret-operator-token-v47zx kubernetes.io/service-account-token 3 1h
default-token-fcjw2 kubernetes.io/service-account-token 3 1h
It was written Creating a new Pod
in logs.
{"level":"info","ts":1549256976.6739526,"logger":"controller_awssecret","caller":"awssecret/awssecret_controller.go:114","msg":"Creating a new Pod","Request.Namespace":"default","Request.Name":"example","Pod.Namespace":"default","Pod.Name":"example-pod"}
However it was written Creating a new Secret
in source codes.
(The same is true for the first implemented commit dd2b3c8)
Is mumoshu/aws-secret-operator:latest
Docker image not latest? Should I use :canary
tag?
Should I build a Docker image myself? Just as written below
aws-secret-operator/deploy/operator.yaml
Lines 18 to 19 in ab65659
Im trying to build the project with a different poll cycle and im experiencing some issues with building the dockerfile.
What i did it is:
FROM golang:1.14 as builder
ENV APP_VERSION=0.3.3
ENV GOOS=linux
ENV GOARCH=amd64
WORKDIR /go/src/github.com/mumoshu/aws-secret-operator
COPY . /go/src/github.com/mumoshu/aws-secret-operator
RUN make build -e GO111MODULE=on
FROM alpine:3.10
RUN apk add --update --no-cache ca-certificates libc6-compat
USER nobody
COPY --from=builder /go/src/github.com/mumoshu/aws-secret-operator/bin/aws-secret-operator /usr/local/bin/aws-secret-operator
Failing with
=> ERROR [builder 4/4] RUN make build -e GO111MODULE=on 0.3s
------
> [builder 4/4] RUN make build -e GO111MODULE=on:
#11 0.278 make: *** No rule to make target 'build'. Stop.
------
failed to solve with frontend dockerfile.v0: failed to build LLB: executor failed running [/bin/sh -c make build -e GO111MODULE=on]: runc did not terminate sucessfully
Create an RDS secret and attempt to use it with this operator
{"level":"error","ts":1552708181.4343886,"logger":"kubebuilder.controller","caller":"controller/controller.go:209","msg":"Reconciler error","Controller":"awssecret-controller","Request":"omnition/svc-auth-secrets","error":"failed to compute secret for cr: failed to get json secret as map: json: cannot unmarshal number into Go value of type string","errorVerbose":"json: cannot unmarshal number into Go value of type string\nfailed to get json secret as map\ngithub.com/mumoshu/aws-secret-operator/pkg/controller/awssecret.(*ReconcileAWSSecret).newSecretForCR\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/pkg/controller/awssecret/awssecret_controller.go:154\ngithub.com/mumoshu/aws-secret-operator/pkg/controller/awssecret.(*ReconcileAWSSecret).Reconcile\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/pkg/controller/awssecret/awssecret_controller.go:107\ngithub.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:207\ngithub.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func1\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:157\ngithub.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait.JitterUntil.func1\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:133\ngithub.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait.JitterUntil\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:134\ngithub.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait.Until\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:88\nruntime.goexit\n\t/usr/local/Cellar/go/1.11/libexec/src/runtime/asm_amd64.s:1333\nfailed to compute secret for cr\ngithub.com/mumoshu/aws-secret-operator/pkg/controller/awssecret.(*ReconcileAWSSecret).Reconcile\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/pkg/controller/awssecret/awssecret_controller.go:109\ngithub.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:207\ngithub.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func1\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:157\ngithub.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait.JitterUntil.func1\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:133\ngithub.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait.JitterUntil\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:134\ngithub.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait.Until\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:88\nruntime.goexit\n\t/usr/local/Cellar/go/1.11/libexec/src/runtime/asm_amd64.s:1333","stacktrace":"github.com/mumoshu/aws-secret-operator/vendor/github.com/go-logr/zapr.(*zapLogger).Error\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/github.com/go-logr/zapr/zapr.go:128\ngithub.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:209\ngithub.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func1\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:157\ngithub.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait.JitterUntil.func1\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:133\ngithub.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait.JitterUntil\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:134\ngithub.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait.Until\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:88"}
This fails because the port is a number instead of a string:
"SecretString": "{"username":"test","password":"test","engine":"postgres","host":"test.c5k1abj62b3x.us-east-2.rds.amazonaws.com","port":5432,"dbname":"test","dbInstanceIdentifier":"test"}",
Hi, I'm trying to deploy aws-secret-operator on EKS 1.24 and I'm getting following error
2023-05-31T09:52:34Z INFO controller.awssecret-controller Starting Controller {"reconciler group": "mumoshu.github.io", "reconciler kind": "AWSSecret"}
2023-05-31T09:52:34Z INFO controller.awssecret-controller Starting workers {"reconciler group": "mumoshu.github.io", "reconciler kind": "AWSSecret", "worker count": 1}
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x14ad515]
goroutine 562 [running]:
github.com/mumoshu/aws-secret-operator/controllers.(*SyncContext).SecretsManagerSecretToKubernetesStringData(0x1624580, {{0xc0009023f0, 0x17f6017}, {0xc000040450, 0xc0009023e0}})
/workspace/controllers/secret.go:58 +0x35
github.com/mumoshu/aws-secret-operator/controllers.(*AWSSecretController).newSecretForCR(0xc000c969f0, 0xc000255380)
/workspace/controllers/awssecret_controller.go:131 +0x10a
github.com/mumoshu/aws-secret-operator/controllers.(*AWSSecretController).Reconcile(0xc000c969f0, {0x1ab2578, 0xc000f06060}, {{{0xc0009023e0, 0x173d660}, {0xc0009023d0, 0x30}}})
/workspace/controllers/awssecret_controller.go:75 +0x265
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Reconcile(0xc00087e6e0, {0x1ab2578, 0xc000ca5f80}, {{{0xc0009023e0, 0x173d660}, {0xc0009023d0, 0x413834}}})
/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:114 +0x26f
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).reconcileHandler(0xc00087e6e0, {0x1ab24d0, 0xc0006bd300}, {0x16863e0, 0xc0003ec580})
/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:311 +0x33e
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem(0xc00087e6e0, {0x1ab24d0, 0xc0006bd300})
/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:266 +0x205
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func2.2()
/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:227 +0x85
created by sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func2
/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:223 +0x357
Anyone had a similar issue?
I deployed aws-secret-operator
on the kubernetes cluster using mumoshu/aws-secret-operator: canary
.
(Related in #1)
However, the following error message was output.
x509: certificate signed by unknown authority
{"level":"error","ts":1549255824.3728073,"logger":"kubebuilder.controller","caller":"controller/controller.go:209","msg":"Reconciler error","Controller":"awssecret-controller","Request":"default/redash-secret","error":"failed to compute secret for cr: failed to get json secret as map: RequestError: send request failed\ncaused by: Post https://secretsmanager.ap-northeast-1.amazonaws.com/: x509: certificate signed by unknown authority","errorVerbose":"RequestError: send request failed\ncaused by: Post https://secretsmanager.ap-northeast-1.amazonaws.com/: x509: certificate signed by unknown authority\nfailed to get json secret as map\ngithub.com/mumoshu/aws-secret-operator/pkg/controller/awssecret.(*ReconcileAWSSecret).newSecretForCR\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/pkg/controller/awssecret/awssecret_controller.go:154\ngithub.com/mumoshu/aws-secret-operator/pkg/controller/awssecret.(*ReconcileAWSSecret).Reconcile\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/pkg/controller/awssecret/awssecret_controller.go:107\ngithub.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:207\ngithub.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func1\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:157\ngithub.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait.JitterUntil.func1\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:133\ngithub.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait.JitterUntil\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:134\ngithub.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait.Until\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:88\nruntime.goexit\n\t/usr/local/Cellar/go/1.11/libexec/src/runtime/asm_amd64.s:1333\nfailed to compute secret for cr\ngithub.com/mumoshu/aws-secret-operator/pkg/controller/awssecret.(*ReconcileAWSSecret).Reconcile\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/pkg/controller/awssecret/awssecret_controller.go:109\ngithub.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:207\ngithub.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func1\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:157\ngithub.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait.JitterUntil.func1\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:133\ngithub.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait.JitterUntil\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:134\ngithub.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait.Until\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:88\nruntime.goexit\n\t/usr/local/Cellar/go/1.11/libexec/src/runtime/asm_amd64.s:1333","stacktrace":"github.com/mumoshu/aws-secret-operator/vendor/github.com/go-logr/zapr.(*zapLogger).Error\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/github.com/go-logr/zapr/zapr.go:128\ngithub.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:209\ngithub.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func1\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:157\ngithub.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait.JitterUntil.func1\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:133\ngithub.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait.JitterUntil\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:134\ngithub.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait.Until\n\t/Users/kuoka-yusuke/go/src/github.com/mumoshu/aws-secret-operator/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:88"}
I think that installation of the ca-certificates
package is necessary below.
aws-secret-operator/build/Dockerfile
Lines 1 to 7 in ab65659
When I create a secret manually e.g. using:
kubectl create secret generic test-secret --namespace epi-dev --from-file=some-file.json
and map the resulting secret as a volume into a pod, then the pod will see a file named some-file.json
in the mapped location.
How can I achieve the same with aws-secret-operator:
Getting the secret value of the AWS Secret as one whole json file in the pod?
Looking into the resulting kubernetes secret, the difference is just the filename within the data like here:
apiVersion: v1
data:
some-file.json: base64-encoded-json-content....
kind: Secret
metadata:
name: test-secret
type: Opaque
The deployment manifest files deploy/namespaced/deployment.yaml
and deploy/cluster_scoped/deployment.yaml
contain a reference to the Docker image as follows:
# Replace this with the built image name
image: mumoshu/aws-secret-operator:v0.1.0
I find the v
prefix in the image tag misleading. Pulling an old image like v0.1.0
requires the v
prefix but pulling a recent image like 0.3.2
does not require the v
prefix and in fact it fails if it is added. I tried with other recent images (e.g. 0.2.4
) and they also fail with the v
prefix.
My suggestion would be to replace v0.1.0
with a more recent image like 0.3.2
in both deployment manifest files. The version number doesn't have to be kept in sync with every release but using a more recent image would make it more seamless for users to update it. The first time I did it I was puzzled because I simply replaced the version number and didn't understand why it failed until I discovered the v
prefix had to be removed.
This is theoretically possible via a mutating webhook similar to bank-vaults'.
When starting this up for the first time I receive an error "Reconciler error" and "failed to compute secret for cr: failed to get json secret as map: NoCredentialProviders: no valid providers in chain."
Would be helpful to have some instructions on how to get credentials in there when needed.
Hi
I created an AwsSecret with labels and annotations, hoping these would be copied over to the created Secret. This seems not to be the case but would be crucial in some cases!
Thanks,
Michael
I have a secret called
apiVersion: mumoshu.github.io/v1alpha1
kind: AWSSecret
metadata:
name: db-secrets
namespace: authentication
spec:
stringDataFrom:
secretsManagerSecretRef:
secretId: mysecret
versionId: ee113603-3254-478a-bb27-40027ae4ff60
I want to be to add multiple entries in 1 secret, is this possible?
Is there already a Helm Chart for this?
There are multiple projects that try to do the same thing conceptually, with CRD-s very similar to this project:
Consider unifying efforts to provide a Common API (eg. CRD) for sourcing secrets into kubernetes.
Ongoing discussion:
I'm creating a local micro version of our environment and use localstack to mock up various AWS services.
Does your aws-secret-operator support localstack integration? I wasn't able to find any such info in your documentation and I don't speak go!
If not, this would be a useful configuration for local development or could also be used if there is a proxy between the container and AWS.
When running cluster-scoped aws-secret-operator with Kubernetes manifests provided by the project, the following error is logged occassionally:
2022-06-16T13:44:37Z ERROR leader Failed to get Node {"Node.Name": "$NODE_NAME_REDACED", "error": "nodes \"$NODE_NAME_REDACTED\" is forbidden: User \"system:serviceaccount:kube-system:aws-secret-operator\" cannot get resource \"nodes\" in API group \"\" at the cluster scope"}
github.com/operator-framework/operator-lib/leader.getNode
/go/pkg/mod/github.com/operator-framework/[email protected]/leader/leader.go:269
github.com/operator-framework/operator-lib/leader.isNotReadyNode
/go/pkg/mod/github.com/operator-framework/[email protected]/leader/leader.go:277
github.com/operator-framework/operator-lib/leader.Become
/go/pkg/mod/github.com/operator-framework/[email protected]/leader/leader.go:182
github.com/mumoshu/aws-secret-operator/cmd.run
/workspace/cmd/root.go:122
github.com/mumoshu/aws-secret-operator/cmd.glob..func1
/workspace/cmd/root.go:60
github.com/spf13/cobra.(*Command).execute
/go/pkg/mod/github.com/spf13/[email protected]/command.go:856
github.com/spf13/cobra.(*Command).ExecuteC
/go/pkg/mod/github.com/spf13/[email protected]/command.go:974
github.com/spf13/cobra.(*Command).Execute
/go/pkg/mod/github.com/spf13/[email protected]/command.go:902
main.main
/workspace/main.go:10
runtime.main
/usr/local/go/src/runtime/proc.go:255
It seems that this is caused by leader-election mechanism in operator-lib/leader library.
RBAC provided in this project doesn't include get
for nodes
.
So my question is that should this permission be included in the RBAC provided by the project
Run aws-secret-operator in cluster-scoped mode.
aws-secret-operator runs without errors.
aws-secret-operator-version: v0.5.2
EKS Kubernetes version: 1.21
I'm happy to create PR adding the missing "get nodes" permissions to RBAC provided by the project, if we agree that it's reasonable action.
Currently updating the secret causes the reconciliation of the operator controller to fail, as it doesn't find any existing secrets and tries to create a new one instead of updating existing.
Fix proposed in #6
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.