Coder Social home page Coder Social logo

codingvirtues / awspca-issuer Goto Github PK

View Code? Open in Web Editor NEW
23.0 5.0 1.0 67 KB

cert-manager for Kubernetes external issuer for AWS Private CA

License: Apache License 2.0

Dockerfile 0.68% Makefile 15.84% Go 83.48%
cert-manager kubernetes-environment issuer certificate certificates-issued

awspca-issuer's Introduction

AWS Certificate Manager Private Certificate Authority

AWS Certificate Manager Private CA is a Certificate Authority managed by AWS (https://aws.amazon.com/certificate-manager/private-certificate-authority/). It allows creation of root and intermediate CA's that can issue certificates for entities blessed by the CA.

cert-manager

cert-manager manages certificates in Kubernetes environment (among others) and keeps track of renewal requirements (https://cert-manager.io/). It supports various in-built issuers that issue the certificates to be managed by cert-manager.

AWS Private CA Issuer

This project plugs into cert-manager as an external issuer that talks to AWS Certificate Manager Private CA to get certificates issued for your Kubernetes environment.

Setup

Install cert-manager first (https://cert-manager.io/docs/installation/kubernetes/), version 0.16.1 or later.

Clone this repo and perform following steps to install controller:

# make build
# make docker
# make deploy

Create secret that holds AWS credentials:

# cat secret.yaml

apiVersion: v1
kind: Secret
metadata:
  name: aws-credentials
  namespace: awspca-issuer-system
data:
  accesskey: <base64 encoding of AWS access key>
  secretkey: <base64 encoding of AWS secret key>
  region: <base64 encoding of AWS region key>
  arn: <base64 encoding of AWS Private CA ARN>

Note: While generating base64 encoding of above fields, ensure there is no newline character included in the encoded string. For example, following command could be used:

echo -n "<access key>" | base64

Apply configuration to create secret:

# kubectl apply -f secret.yaml

Create resource AWSPCAIssuer for our controller:

# cat issuer.yaml

apiVersion: certmanager.awspca/v1alpha2
kind: AWSPCAIssuer
metadata:
  name: awspca-issuer
  namespace: awspca-issuer-system
spec:
  provisioner:
    name: aws-credentials
    accesskeyRef:
      key: accesskey
    secretkeyRef:
      key: secretkey
    regionRef:
      key: region
    arnRef:
      key: arn

Apply this configuration:

# kubectl apply -f issuer.yaml

# kubectl describe AWSPCAIssuer -n awspca-issuer-system

Name:         awspca-issuer
Namespace:    awspca-issuer-system
Labels:       <none>
Annotations:  API Version:  certmanager.awspca/v1alpha2
Kind:         AWSPCAIssuer
...
Spec:
  Provisioner:
    Accesskey Ref:
      Key:  accesskey
    Arn Ref:
      Key:  arn
    Name:   aws-credentials
    Region Ref:
      Key:  region
    Secretkey Ref:
      Key:  secretkey
Status:
  Conditions:
    Last Transition Time:  2020-08-18T04:34:33Z
    Message:               AWSPCAIssuer verified and ready to sign certificates
    Reason:                Verified
    Status:                True
    Type:                  Ready
Events:
  Type    Reason    Age                    From                     Message
  ----    ------    ----                   ----                     -------
  Normal  Verified  8m22s (x2 over 8m22s)  awspcaissuer-controller  AWSPCAIssuer verified and ready to sign certificates

Now create certificate:

# cat certificate.yaml

apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadata:
  name: backend-awspca
  namespace: awspca-issuer-system
spec:
  # The secret name to store the signed certificate
  secretName: backend-awspca-tls
  # Common Name
  commonName: foo.com
  # DNS SAN
  dnsNames:
    - localhost
    - foo.com
  # IP Address SAN
  ipAddresses:
    - "127.0.0.1"
  # Duration of the certificate
  duration: 24h
  # Renew 1 hour before the certificate expiration
  renewBefore: 1h
  isCA: false
  # The reference to the step issuer
  issuerRef:
    group: certmanager.awspca
    kind: AWSPCAIssuer
    name: awspca-issuer
# kubectl apply -f certificate.yaml
# kubectl describe Certificate backend-awspca -n awspca-issuer-system

Name:         backend-awspca
Namespace:    awspca-issuer-system
Labels:       <none>
Annotations:  API Version:  cert-manager.io/v1alpha3
Kind:         Certificate
...
Spec:
  Common Name:  foo.com
  Dns Names:
    localhost
    foo.com
  Duration:  24h0m0s
  Ip Addresses:
    127.0.0.1
  Issuer Ref:
    Group:       certmanager.awspca
    Kind:        AWSPCAIssuer
    Name:        awspca-issuer
  Renew Before:  1h0m0s
  Secret Name:   backend-awspca-tls
Status:
  Conditions:
    Last Transition Time:  2020-08-18T04:34:48Z
    Message:               Certificate is up to date and has not expired
    Reason:                Ready
    Status:                True
    Type:                  Ready
  Not After:               2020-08-19T04:34:45Z
  Not Before:              2020-08-18T03:34:45Z
  Renewal Time:            2020-08-19T03:34:45Z
  Revision:                1
Events:
  Type    Reason     Age    From          Message
  ----    ------     ----   ----          -------
  Normal  Issuing    6m1s   cert-manager  Issuing certificate as Secret does not exist
  Normal  Generated  6m     cert-manager  Stored new private key in temporary Secret resource "backend-awspca-7m9sx"
  Normal  Requested  6m     cert-manager  Created new CertificateRequest resource "backend-awspca-m2gz5"
  Normal  Issuing    5m51s  cert-manager  The certificate has been successfully issued

Check certificate and private key are present in secrets:

# kubectl describe secrets backend-awspca-tls -n awspca-issuer-system   

Name:         backend-awspca-tls
Namespace:    awspca-issuer-system
Labels:       <none>
Annotations:  cert-manager.io/alt-names: localhost,foo.com
              cert-manager.io/certificate-name: backend-awspca
              cert-manager.io/common-name: foo.com
              cert-manager.io/ip-sans: 127.0.0.1
              cert-manager.io/issuer-kind: AWSPCAIssuer
              cert-manager.io/issuer-name: awspca-issuer
              cert-manager.io/uri-sans:

Type:  kubernetes.io/tls

Data
====
tls.key:  xxxx bytes
tls.crt:  yyyy bytes

awspca-issuer's People

Contributors

sudhindra-hub avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

Forkers

yuhusn

awspca-issuer's Issues

Is this project actively maintained

The promise of this project is great - but it seems like it's been dropped by the developer. The developer is not even an active team member at this point. I am opening up this discussion PR to see if we should try to take this project over in another repository somewhere?

Support standard AWS SDK Credential mechanisms

The current implementation (since 6629878) requires the controller to get its credentials from a Secret object. Can you make that a conditional only if the secret is defined, and support the default credential chain? This will allow operators to use standard means like IAM Roles for Service Accounts, secrets as a pod's environment variables. The SDK region should be inferred from the standard configuration points too (env var/config file/IMDS).

It would be really nice to not have to reference a secret to set non-secret values such as the Cert ARN in the provisioner, and just directly state that value.

The issuer crashes when cert resources are created without durations

Within the cert-manager documentation the certificate spec states that the duration field is optional. When I was testing the pca issuer I noticed the controller crashed when I didn't specify a duration.

sample manifest to cause the crash

apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadata:
  name: bug-test
  namespace: awspca-issuer-system
spec:
  issuerRef:
    group: certmanager.awspca
    kind: AWSPCAIssuer
    name: awspca-issuer
  secretName: bug-test
  commonName: foo.com
  # DNS SAN
  dnsNames:
    - localhost
    - foo.com
  # IP Address SAN
  ipAddresses:
    - "127.0.0.1"
  # Duration of the certificate
  #   Renew 1 hour before the certificate expiration
  #  renewBefore: 1h
  isCA: false

I think this line is the cause of the crash. Would it be possible to slip in a default duration of 24 hours to prevent crashes for future users?

cparams := acmpca.IssueCertificateInput{
CertificateAuthorityArn: aws.String(p.arn),
SigningAlgorithm: aws.String(acmpca.SigningAlgorithmSha256withrsa),
Csr: cr.Spec.CSRPEM,
Validity: &acmpca.Validity {
Type: aws.String(acmpca.ValidityPeriodTypeDays),
Value: aws.Int64(int64(cr.Spec.Duration.Hours()/24)),
},
IdempotencyToken: aws.String("awspca"),
}

edited to add:

I left out the stack trace so I added it. I apologize for the log being partially cut off.

2020-10-09T20:14:42.809Z    INFO    controller-runtime.metrics    metrics server is starting to listen    {"addr": "127.0.0.1:8080"}
2020-10-09T20:14:42.893Z    INFO    setup    starting manager
I1009 20:14:42.894315       1 leaderelection.go:242] attempting to acquire leader lease  awspca-issuer-system/controller-leader-election-helper...
2020-10-09T20:14:42.894Z    INFO    controller-runtime.manager    starting metrics server    {"path": "/metrics"}
I1009 20:15:00.299854       1 leaderelection.go:252] successfully acquired lease awspca-issuer-system/controller-leader-election-helper
2020-10-09T20:15:00.299Z    DEBUG    controller-runtime.manager.events    Normal    {"object": {"kind":"ConfigMap","namespace":"awspca-issuer-system","name":"controller-leader-election-helper","uid":"2a543a93-bd67-42e1-b809-ccaf2ffa394c","apiVersion":"v1","resourceVersion":"1311092"}, "reason": "LeaderElection", "message": "awspca-issuer-controller-manager-6b58d94657-nqxcb_3693e870-ac71-493e-9eaa-41afe7c555dc became leader"}
2020-10-09T20:15:00.300Z    INFO    controller-runtime.controller    Starting EventSource    {"controller": "certificaterequest", "source": "kind source: /, Kind="}
2020-10-09T20:15:00.300Z    INFO    controller-runtime.controller    Starting EventSource    {"controller": "awspcaissuer", "source": "kind source: /, Kind="}
2020-10-09T20:15:00.400Z    INFO    controller-runtime.controller    Starting Controller    {"controller": "certificaterequest"}
2020-10-09T20:15:00.400Z    INFO    controller-runtime.controller    Starting Controller    {"controller": "awspcaissuer"}
2020-10-09T20:15:00.400Z    INFO    controller-runtime.controller    Starting workers    {"controller": "awspcaissuer", "worker count": 1}
2020-10-09T20:15:00.400Z    INFO    controller-runtime.controller    Starting workers    {"controller": "certificaterequest", "worker count": 1}
2020-10-09T20:15:00.401Z    ERROR    controllers.CertificateRequest    failed to provisioner for AWSPCAIssuer resource    {"certificaterequest": "awspca-issuer-system/serena-jks-test-dw84n", "error": "provisioner awspca-issuer-system/awspca-issuer not found"}
github.com/go-logr/zapr.(*zapLogger).Error
    /Users/[redacted]/go/pkg/mod/github.com/go-logr/[email protected]/zapr.go:128
github.com/awspca-issuer/controllers.(*CertificateRequestReconciler).Reconcile
    /Users/[redacted]/repos/awspca-issuer/controllers/certificaterequest_controller.go:108
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).reconcileHandler
    /Users/[redacted]/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:256
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem
    /Users/[redacted]/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:232
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).worker
    /Users/[redacted]/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:211
k8s.io/apimachinery/pkg/util/wait.JitterUntil.func1
    /Users/[redacted]/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:152
k8s.io/apimachinery/pkg/util/wait.JitterUntil
    /Users/[redacted]/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:153
k8s.io/apimachinery/pkg/util/wait.Until
    /Users/[redacted]/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:88
I1009 20:15:00.401315       1 conditions.go:200] Setting lastTransitionTime for CertificateRequest "serena-jks-test-dw84n" condition "Ready" to 2020-10-09 20:15:00.4013063 +0000 UTC m=+18.716761101
2020-10-09T20:15:00.402Z    DEBUG    controller-runtime.manager.events    Warning    {"object": {"kind":"CertificateRequest","namespace":"awspca-issuer-system","name":"serena-jks-test-dw84n","uid":"f124c674-17bf-4828-9565-e36234fd3caf","apiVersion":"cert-manager.io/v1alpha2","resourceVersion":"1311018"}, "reason": "Pending", "message": "Failed to load provisioner for AWSPCAIssuer resource awspca-issuer-system/awspca-issuer"}
2020-10-09T20:15:00.595Z    ERROR    controller-runtime.controller    Reconciler error    {"controller": "certificaterequest", "request": "awspca-issuer-system/serena-jks-test-dw84n", "error": "provisioner awspca-issuer-system/awspca-issuer not found"}
github.com/go-logr/zapr.(*zapLogger).Error
    /Users/[redacted]/go/pkg/mod/github.com/go-logr/[email protected]/zapr.go:128
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).reconcileHandler
    /Users/[redacted]/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:258
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem
    /Users/[redacted]/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:232
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).worker
    /Users/[redacted]/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:211
k8s.io/apimachinery/pkg/util/wait.JitterUntil.func1
    /Users/[redacted]/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:152
k8s.io/apimachinery/pkg/util/wait.JitterUntil
    /Users/[redacted]/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:153
k8s.io/apimachinery/pkg/util/wait.Until
    /Users/[redacted]/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:88
2020-10-09T20:15:01.001Z    DEBUG    controller-runtime.manager.events    Normal    {"object": {"kind":"AWSPCAIssuer","namespace":"awspca-issuer-system","name":"awspca-issuer","uid":"989c4d9e-4206-4bc2-af0b-8483dd6c5c32","apiVersion":"certmanager.awspca/v1alpha2","resourceVersion":"586343"}, "reason": "Verified", "message": "AWSPCAIssuer verified and ready to sign certificates"}
2020-10-09T20:15:01.014Z    DEBUG    controller-runtime.controller    Successfully Reconciled    {"controller": "awspcaissuer", "request": "awspca-issuer-system/awspca-issuer"}
I1009 20:15:05.464122       1 conditions.go:189] Found status change for CertificateRequest "serena-jks-test-dw84n" condition "Ready": "False" -> "True"; setting lastTransitionTime to 2020-10-09 20:15:05.4641086 +0000 UTC m=+23.779563401
2020-10-09T20:15:05.464Z    DEBUG    controller-runtime.manager.events    Normal    {"object": {"kind":"CertificateRequest","namespace":"awspca-issuer-system","name":"serena-jks-test-dw84n","uid":"f124c674-17bf-4828-9565-e36234fd3caf","apiVersion":"cert-manager.io/v1alpha2","resourceVersion":"1311097"}, "reason": "Issued", "message": "Certificate issued"}
2020-10-09T20:15:05.599Z    DEBUG    controller-runtime.controller    Successfully Reconciled    {"controller": "certificaterequest", "request": "awspca-issuer-system/serena-jks-test-dw84n"}
2020-10-09T20:15:05.614Z    DEBUG    controller-runtime.controller    Successfully Reconciled    {"controller": "certificaterequest", "request": "awspca-issuer-system/serena-jks-test-dw84n"}
2020-10-09T20:19:00.651Z    DEBUG    controller-runtime.controller    Successfully Reconciled    {"controller": "certificaterequest", "request": "awspca-issuer-system/serena-jks-test-dw84n"}
I1009 20:19:12.906657       1 conditions.go:200] Setting lastTransitionTime for CertificateRequest "serena-jks-test-vkcmc" condition "Ready" to 2020-10-09 20:19:12.9066441 +0000 UTC m=+271.222098901
2020-10-09T20:19:12.907Z    DEBUG    controller-runtime.manager.events    Normal    {"object": {"kind":"CertificateRequest","namespace":"awspca-issuer-system","name":"serena-jks-test-vkcmc","uid":"c4222d26-66aa-43e7-b410-daeeed4a9b03","apiVersion":"cert-manager.io/v1alpha2","resourceVersion":"1312140"}, "reason": "Issued", "message": "Certificate issued"}
2020-10-09T20:19:13.026Z    DEBUG    controller-runtime.controller    Successfully Reconciled    {"controller": "certificaterequest", "request": "awspca-issuer-system/serena-jks-test-vkcmc"}
2020-10-09T20:19:13.031Z    DEBUG    controller-runtime.controller    Successfully Reconciled    {"controller": "certificaterequest", "request": "aw
E1009 20:20:42.687084       1 runtime.go:78] Observed a panic: "invalid memory address or nil pointer dereference" (runtime error: invalid memory address or nil pointer dereference)
goroutine 274 [running]:
k8s.io/apimachinery/pkg/util/runtime.logPanic(0x1572e60, 0x220f470)
    /Users/[redacted]/go/pkg/mod/k8s.io/[email protected]/pkg/util/runtime/runtime.go:74 +0xa6
k8s.io/apimachinery/pkg/util/runtime.HandleCrash(0x0, 0x0, 0x0)
    /Users/[redacted]/go/pkg/mod/k8s.io/[email protected]/pkg/util/runtime/runtime.go:48 +0x89
panic(0x1572e60, 0x220f470)
    /usr/local/Cellar/go/1.15/libexec/src/runtime/panic.go:969 +0x175
github.com/awspca-issuer/provisioners.(*AWSPCAProvisioner).Sign(0xc00065cb00, 0x1926440, 0xc000048210, 0xc00038c5a0, 0xc00065cb00, 0x1, 0x0, 0x0, 0xc000386da0, 0x14, ...)
    /Users/[redacted]/repos/awspca-issuer/provisioners/awspca.go:107 +0x569
github.com/awspca-issuer/controllers.(*CertificateRequestReconciler).Reconcile(0xc00045fe90, 0xc000af50a0, 0x14, 0xc000af5080, 0x15, 0x540d64c179, 0xc00013d8c0, 0xc000678248, 0xc000678240)
    /Users/[redacted]/repos/awspca-issuer/controllers/certificaterequest_controller.go:114 +0x70e
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).reconcileHandler(0xc0002749c0, 0x15c3e40, 0xc000cd74c0, 0x0)
    /Users/[redacted]/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:256 +0x166
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem(0xc0002749c0, 0xc000624400)
    /Users/[redacted]/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:232 +0xb0
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).worker(0xc0002749c0)
    /Users/[redacted]/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:211 +0x2b
k8s.io/apimachinery/pkg/util/wait.JitterUntil.func1(0xc0003d0750)
    /Users/[redacted]/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:152 +0x5f
k8s.io/apimachinery/pkg/util/wait.JitterUntil(0xc0003d0750, 0x3b9aca00, 0x0, 0x1, 0xc0000461e0)
    /Users/[redacted]/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:153 +0x105
k8s.io/apimachinery/pkg/util/wait.Until(0xc0003d0750, 0x3b9aca00, 0xc0000461e0)
    /Users/[redacted]/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:88 +0x4d
created by sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func1
    /Users/[redacted]/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:193 +0x32d
panic: runtime error: invalid memory address or nil pointer dereference [recovered]
    panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0xcabe89]
goroutine 274 [running]:
k8s.io/apimachinery/pkg/util/runtime.HandleCrash(0x0, 0x0, 0x0)
    /Users/[redacted]/go/pkg/mod/k8s.io/[email protected]/pkg/util/runtime/runtime.go:55 +0x10c
panic(0x1572e60, 0x220f470)
    /usr/local/Cellar/go/1.15/libexec/src/runtime/panic.go:969 +0x175
github.com/awspca-issuer/provisioners.(*AWSPCAProvisioner).Sign(0xc00065cb00, 0x1926440, 0xc000048210, 0xc00038c5a0, 0xc00065cb00, 0x1, 0x0, 0x0, 0xc000386da0, 0x14, ...)
    /Users/[redacted]/repos/awspca-issuer/provisioners/awspca.go:107 +0x569
github.com/awspca-issuer/controllers.(*CertificateRequestReconciler).Reconcile(0xc00045fe90, 0xc000af50a0, 0x14, 0xc000af5080, 0x15, 0x540d64c179, 0xc00013d8c0, 0xc000678248, 0xc000678240)
    /Users/[redacted]/repos/awspca-issuer/controllers/certificaterequest_controller.go:114 +0x70e
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).reconcileHandler(0xc0002749c0, 0x15c3e40, 0xc000cd74c0, 0x0)
    /Users/[redacted]/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:256 +0x166
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem(0xc0002749c0, 0xc000624400)
    /Users/[redacted]/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:232 +0xb0
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).worker(0xc0002749c0)
    /Users/[redacted]/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:211 +0x2b
k8s.io/apimachinery/pkg/util/wait.JitterUntil.func1(0xc0003d0750)
    /Users/[redacted]/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:152 +0x5f
k8s.io/apimachinery/pkg/util/wait.JitterUntil(0xc0003d0750, 0x3b9aca00, 0x0, 0x1, 0xc0000461e0)
    /Users/[redacted]/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:153 +0x105
k8s.io/apimachinery/pkg/util/wait.Until(0xc0003d0750, 0x3b9aca00, 0xc0000461e0)
    /Users/[redacted]/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:88 +0x4d
created by sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func1
    /Users/[redacted]/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:193 +0x32d

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.