diff --git a/README.md b/README.md index 88e9534f..c3bb0911 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,72 @@ # offline-license-server +AppsCode License server. We call it `offline` license server because once you have received the license file, no further connection is required with the license server. So, these licenses can be used within an air-gapped Kubernetes cluster. + +## API Reference + +### Cluster UID + +We use the `uid` of the `kube-system` namespace as the Kubernetes cluster UID. Please run the command below to get the cluster uid for your cluster: + +```console +kubectl get ns kube-system -o=jsonpath='{.metadata.uid}' +``` + +### License Issuer CA + +The license issuer ca can be found here: https://licenses.appscode.com/certificates/ca.crt + +### List of products + +- kubedb-community +- kubedb-enterprise +- stash-community +- stash-enterprise + +### Email Address Requirements + +You must provide a valid non-disposable email to acquire license. For Enterprise products, you must provide a valid work email to acquire license. + +### Register Email + +Make the api call below with a valid email address. We are going to email you a token for the License server. + +```console +curl -d "email=***" -X POST https://license-issuer.appscode.com/register +``` + +### Issue License + +You can use the `{email, token}` to issue license using `curl` from command line. In the example below replace `***` with an actual token you have received in the email. + +```console +# pass request body as application/x-www-form-urlencoded + +curl -X POST \ + -d "name=***&email=***&product=kubedb-community&cluster=***&tos=true&token=***" \ + https://license-issuer.appscode.com/issue-license + +# pass request body as application/json + +curl -X POST -H "Content-Type: application/json" \ + -d '{"name":"***","email":"***","product":"kubedb-community","cluster":"***","tos":"true","token":"***"}' \ + https://license-issuer.appscode.com/issue-license + +# pretty printed request json body +{ + "name": "***", + "email": "***", + "product": "kubedb-community", + "cluster": "***", + "tos": "true", + "token": "***" +} +``` + ## Installation +These instructions are useful if you are trying to deploy your own license server or update an existing license server. + - Download pre-built binary into a server ```console @@ -31,9 +96,3 @@ sudo systemctl enable offline-license-server.service sudo systemctl start offline-license-server sudo journalctl -f -u offline-license-server ``` - -## Verify Email - -``` -curl -d "email=tamal@appscode.com" -X POST http://localhost:4000/register -``` diff --git a/pkg/server/server.go b/pkg/server/server.go index 909af3c8..1711e5f5 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -181,9 +181,9 @@ func (s *Server) HandleRegisterEmail(req RegisterRequest) error { } { - subject := "Token for AppsCode License server" + subject := "AppsCode license server token" src := `Hi, -Please use the token below to issue licenses with this email. +Please use the token below to issue licenses using this email address. {{.Token}} @@ -315,16 +315,15 @@ AppsCode Team` } } - // mark email as verified - if exists, err := s.fs.Exists(context.TODO(), EmailVerifiedPath(domain, info.Email)); err == nil && !exists { - err = s.fs.WriteFile(context.TODO(), EmailVerifiedPath(domain, info.Email), []byte(timestamp)) - if err != nil { - return err - } - } - { if info.Token != "" { + // mark email as verified + if exists, err := s.fs.Exists(context.TODO(), EmailVerifiedPath(domain, info.Email)); err == nil && !exists { + err = s.fs.WriteFile(context.TODO(), EmailVerifiedPath(domain, info.Email), []byte(timestamp)) + if err != nil { + return err + } + } respond(ctx, crtLicense) } else { respond(ctx, []byte("Your license has been emailed!")) @@ -337,7 +336,7 @@ AppsCode Team` func (s *Server) GetDomainLicense(domain string, product string) (*ProductLicense, error) { if !emailproviders.IsWorkEmail(domain) { if IsEnterpriseProduct(product) { - return nil, apierrors.NewBadRequest("requires work email for enterprise license") + return nil, apierrors.NewBadRequest("Please provide work email to issue license for Enterprise products.") } ttl := metav1.Duration{Duration: DefaultTTLForCommunityProduct} return &ProductLicense{ diff --git a/pkg/server/types.go b/pkg/server/types.go index f20e946b..e1c3e26f 100644 --- a/pkg/server/types.go +++ b/pkg/server/types.go @@ -44,7 +44,7 @@ type LicenseForm struct { Name string `form:"name" binding:"Required" json:"name"` Email string `form:"email" binding:"Required;Email" json:"email"` Product string `form:"product" binding:"Required" json:"product"` - Cluster string `form:"cluster-uid" binding:"Required" json:"cluster"` + Cluster string `form:"cluster" binding:"Required" json:"cluster"` Tos string `form:"tos" binding:"Required" json:"tos"` Token string `form:"token" json:"token"` } diff --git a/templates/bindata.go b/templates/bindata.go index 582256fa..d1243495 100644 --- a/templates/bindata.go +++ b/templates/bindata.go @@ -77,7 +77,7 @@ func (fi bindataFileInfo) Sys() interface{} { return nil } -var _indexHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xcc\x57\xcd\x72\xdc\x36\x0c\xbe\xf7\x29\x10\x5e\x72\xa9\x96\xc9\xad\xcd\x50\x9a\xb6\xb6\x0f\x99\x76\xda\x4c\x9d\x4b\x8f\x5c\x12\xbb\x62\x4c\x91\x1c\x02\xda\x78\xa7\xd3\x77\xef\x50\xd2\xae\xd7\x2b\xa5\xfe\x89\x33\x53\x1f\x6c\x41\xf8\xf9\x88\x8f\x00\x04\xab\x57\x97\x7f\x5c\x7c\xfc\xeb\xc3\x15\xb4\xdc\xf9\xe6\x3b\x35\xfe\x01\x50\x2d\x6a\x5b\x1e\x00\x54\x87\xac\xc1\xb4\x3a\x13\x72\x2d\x7a\xde\x54\x3f\x08\x90\xa7\xca\xa0\x3b\xac\xc5\xce\xe1\xe7\x14\x33\x0b\x30\x31\x30\x06\xae\xc5\x67\x67\xb9\xad\x2d\xee\x9c\xc1\x6a\x10\xbe\x07\x17\x1c\x3b\xed\x2b\x32\xda\x63\xfd\xf6\x2e\x14\x3b\xf6\xd8\xfc\x9c\x12\x5d\x44\x8b\xf0\x9b\x33\x18\x08\xe1\x1a\xf3\x0e\xb3\x92\xa3\x7a\x34\xf5\x2e\xdc\x0c\x4f\x00\x19\x7d\x2d\x88\xf7\x1e\xa9\x45\x64\x31\xbd\x6e\x33\x6e\x6a\xd1\x32\x27\x7a\x27\xa5\xb1\x61\xf5\x89\x2c\x7a\xb7\xcb\xab\x80\x2c\x43\xea\xe4\xba\xf7\x9d\xfe\xe9\xcd\xea\xc7\xd5\x1b\x69\x88\x46\x79\xd5\xb9\xb0\x32\x44\x63\x9c\xe1\x68\x4a\x1e\xc8\x50\xeb\x68\xf7\xd3\x11\x08\x0d\xbb\x18\xc0\x78\x4d\x54\x8b\x49\x14\xcd\x84\xaf\xac\xdb\x1d\x74\x85\x0e\xed\x02\xe6\xa3\xb6\x10\xfc\xf6\xa0\x1e\x12\x3b\x51\x01\x7c\x81\x83\x3b\x67\xd9\xbe\x3d\x09\xb5\x89\xb9\x03\x3d\xe0\xd7\x42\x3a\xa2\x1e\x2b\x3f\x7a\x0a\xe8\x90\xdb\x68\x6b\x91\x22\xf1\x3d\x90\xd3\x13\x6e\x1c\x7a\x7b\x4f\x5b\x48\xd6\x6b\xf4\x07\x8b\x41\x10\xcd\xef\xba\x43\x25\x07\xe1\xcc\xfa\x2c\xdf\x1c\xfd\x59\x3c\x00\xe5\x42\xea\xf9\xec\x25\x4c\xd5\x53\x7e\x8b\x99\x6e\x8a\x38\x38\xce\xb5\xbc\x4f\x58\x0b\xc6\xdb\x05\x5d\xf2\xda\x60\x1b\xbd\xc5\x5c\x8b\x73\xb5\x3c\x3b\xbc\xb4\x6e\x77\x8f\x9b\xd9\x8b\xe7\x90\x75\xd5\x69\xe7\x1f\xcb\x16\xb4\x9a\x2a\x67\x62\xa0\xca\xe3\x86\x4f\xc4\xec\xb6\x2d\x3f\x8d\x4c\x2c\xc8\xcf\x63\xf3\x0b\xae\xff\x49\x27\xc0\x4e\xfb\x1e\x1f\xe4\xb9\xb4\x4d\xd2\xc7\x9e\x29\xe9\x81\xa3\x8a\x3a\xed\x7d\x79\x28\x89\xcf\x12\x2d\xa9\x1e\xa9\xd7\x04\x1b\x5d\x61\xd8\xa1\x8f\x09\x45\xa3\xa4\x9b\x41\xc8\x82\xf1\x34\xe0\x65\x8a\x97\x90\x6f\x8d\xd7\x9d\x2e\xad\x56\x71\x76\x3a\x6c\xfd\xe3\x4f\x31\xab\x2a\x00\xf5\xaa\xaa\x40\xa5\x03\x4a\x8b\x3e\x95\xf3\x58\x1d\xb6\x65\x5c\x7c\x6c\x1d\xc1\x70\x23\xe0\x08\x5c\xd8\x69\xef\xac\x92\xa9\x81\xaa\x7a\xf9\x7a\xfd\x90\xa3\xed\x0d\x3f\xbf\xbf\x4f\x6c\x08\x3d\x9a\x45\x4a\x47\x0d\xb8\x32\x93\x46\x40\x31\x55\xed\x41\x9c\x3b\x01\xa8\x98\x86\x71\x3b\x15\xda\x4d\xbf\x46\xbb\xae\x4c\xec\xba\x3e\x38\xde\xcf\x2b\xb2\xfc\x34\xbf\xf6\x6b\xbc\xfc\x05\x2e\x0e\x66\x70\x65\x5d\x09\xa3\xe4\x18\x6e\xc1\xeb\xf1\xe0\x18\x18\x73\xca\x8e\x16\xe6\xd6\x29\xfa\xd5\xd1\xee\x65\xe0\x89\x35\xb5\x0f\xa6\x7e\x5d\xac\x5e\x3a\xf3\x11\xfa\xc1\xc4\x47\xec\xaf\xcc\x5b\xc9\xb1\x52\xe6\x9d\x35\xef\xa2\x6f\x33\xbf\xcb\xfd\xe5\x80\x8c\x04\x17\xbe\x27\xc6\x0c\xef\x2f\xbf\xcd\xd7\xcf\x8c\xf1\xab\xde\xd9\xff\xcd\x47\x10\x16\x06\x93\x0b\x9b\x28\x9a\x3f\xfb\x00\xa5\xfe\x74\xb0\xef\x40\x99\x68\xb1\x29\x3d\x61\xd8\xc3\x16\x19\x02\x41\x11\x2b\xda\x13\x63\x07\x55\xac\x3f\x51\x0c\x49\x73\x5b\xbf\xfe\x7b\x55\x36\x46\xab\x59\xaf\x7a\x67\xff\x79\xad\xe4\xe0\x5e\x66\xda\x57\xdd\xdf\x63\x2e\xe0\xde\x1d\x9b\x16\xcd\xcd\x3a\xde\x2e\x4e\xfd\xc2\xf4\x74\x33\x1c\x49\x4c\x1c\x1f\x5d\x0e\xed\xc0\xb9\x47\x31\xff\xc8\x01\xbc\x07\xbd\xcd\x88\xc0\x11\xb8\xc5\x39\x80\x3e\xdb\x4f\x75\x4a\x54\x78\x58\x99\xd8\x49\x8f\x5b\xed\x25\x47\x92\x4b\xed\xd5\x30\xe6\x8e\x40\x07\x5b\xd6\xec\xb1\xaf\x48\x49\x3d\x33\x9d\xf7\xcd\x52\xe1\x3e\xbd\x73\x4a\x19\x6c\x73\xec\x13\x3e\xeb\x12\xd6\x3d\xf3\xdd\xda\x3c\x49\xe5\xdb\xef\xc2\x8d\x68\xae\xfb\x75\xe7\x58\xc9\xf1\xfd\xd3\xce\xaa\x64\x59\x84\x8f\x0b\xf8\x9d\xb2\x4c\x92\x61\x3b\x1e\xb7\xf9\x71\x89\x57\x72\xfc\x5f\xe7\xdf\x00\x00\x00\xff\xff\x87\x5e\xe1\x70\x03\x0d\x00\x00") +var _indexHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xcc\x57\xcd\x72\xdc\x36\x0c\xbe\xf7\x29\x10\x5e\x72\xa9\x96\xc9\xad\xcd\x50\x9a\xb6\xb6\x0f\x99\x76\xda\x4c\x9d\x4b\x8f\x5c\x12\xbb\x62\x4c\x91\x1c\x02\xda\x78\xa7\xd3\x77\xef\x50\xd2\xae\xd7\x2b\xa5\xfe\x89\x33\x53\x1f\x6c\x41\xf8\xf9\x88\x8f\x00\x04\xab\x57\x97\x7f\x5c\x7c\xfc\xeb\xc3\x15\xb4\xdc\xf9\xe6\x3b\x35\xfe\x01\x50\x2d\x6a\x5b\x1e\x00\x54\x87\xac\xc1\xb4\x3a\x13\x72\x2d\x7a\xde\x54\x3f\x08\x90\xa7\xca\xa0\x3b\xac\xc5\xce\xe1\xe7\x14\x33\x0b\x30\x31\x30\x06\xae\xc5\x67\x67\xb9\xad\x2d\xee\x9c\xc1\x6a\x10\xbe\x07\x17\x1c\x3b\xed\x2b\x32\xda\x63\xfd\xf6\x2e\x14\x3b\xf6\xd8\xfc\x9c\x12\x5d\x44\x8b\xf0\x9b\x33\x18\x08\xe1\x1a\xf3\x0e\xb3\x92\xa3\x7a\x34\xf5\x2e\xdc\x0c\x4f\x00\x19\x7d\x2d\x88\xf7\x1e\xa9\x45\x64\x31\xbd\x6e\x33\x6e\x6a\xd1\x32\x27\x7a\x27\xa5\xb1\x61\xf5\x89\x2c\x7a\xb7\xcb\xab\x80\x2c\x43\xea\xe4\xba\xf7\x9d\xfe\xe9\xcd\xea\xc7\xd5\x1b\x69\x88\x46\x79\xd5\xb9\xb0\x32\x44\x63\x9c\xe1\x68\x4a\x1e\xc8\x50\xeb\x68\xf7\xd3\x11\x08\x0d\xbb\x18\xc0\x78\x4d\x54\x8b\x49\x14\xcd\x84\xaf\xac\xdb\x1d\x74\x85\x0e\xed\x02\xe6\xa3\xb6\x10\xfc\xf6\xa0\x1e\x12\x3b\x51\x01\x7c\x81\x83\x3b\x67\xd9\xbe\x3d\x09\xb5\x89\xb9\x03\x3d\xe0\xd7\x42\x3a\xa2\x1e\x2b\x3f\x7a\x0a\xe8\x90\xdb\x68\x6b\x91\x22\xf1\x3d\x90\xd3\x13\x6e\x1c\x7a\x7b\x4f\x5b\x48\xd6\x6b\xf4\x07\x8b\x41\x10\xcd\xef\xba\x43\x25\x07\xe1\xcc\xfa\x2c\xdf\x1c\xfd\x59\x3c\x00\xe5\x42\xea\xf9\xec\x25\x4c\xd5\x53\x7e\x8b\x99\x6e\x8a\x38\x38\xce\xb5\xbc\x4f\x58\x0b\xc6\xdb\x05\x5d\xf2\xda\x60\x1b\xbd\xc5\x5c\x8b\x73\xb5\x3c\x3b\xbc\xb4\x6e\x77\x8f\x9b\xd9\x8b\xe7\x90\x75\xd5\x69\xe7\x1f\xcb\x16\xb4\x9a\x2a\x67\x62\xa0\xca\xe3\x86\x4f\xc4\xec\xb6\x2d\x3f\x8d\x4c\x2c\xc8\xcf\x63\xf3\x0b\xae\xff\x49\x27\xc0\x4e\xfb\x1e\x1f\xe4\xb9\xb4\x4d\xd2\xc7\x9e\x29\xe9\x81\xa3\x8a\x3a\xed\x7d\x79\x28\x89\xcf\x12\x2d\xa9\x1e\xa9\xd7\x04\x1b\x5d\x61\xd8\xa1\x8f\x09\x45\xa3\xa4\x9b\x41\xc8\x82\xf1\x34\xe0\x65\x8a\x97\x90\x6f\x8d\xd7\x9d\x2e\xad\x56\x71\x76\x3a\x6c\xfd\xe3\x4f\x31\xab\x2a\x00\xf5\xaa\xaa\x40\xa5\x03\x4a\x8b\x3e\x95\xf3\x58\x1d\xb6\x65\x5c\x7c\x6c\x1d\xc1\x70\x23\xe0\x08\x5c\xd8\x69\xef\xac\x92\xa9\x81\xaa\x7a\xf9\x7a\xfd\x90\xa3\xed\x0d\x3f\xbf\xbf\x4f\x6c\x08\x3d\x9a\x45\x4a\x47\x0d\xb8\x32\x93\x46\x40\x31\x55\xed\x41\x9c\x3b\x01\xa8\x98\x86\x71\x3b\x15\xda\x4d\xbf\x46\xbb\xae\x4c\xec\xba\x3e\x38\xde\xcf\x2b\xb2\xfc\x34\xbf\xf6\x6b\xbc\xfc\x05\x2e\x0e\x66\x70\x65\x5d\x09\xa3\xe4\x18\x6e\xc1\xeb\xf1\xe0\x18\x18\x73\xca\x8e\x16\xe6\xd6\x29\xfa\xd5\xd1\xee\x65\xe0\x89\x35\xb5\x0f\xa6\x7e\x5d\xac\x5e\x3a\xf3\x11\xfa\xc1\xc4\x47\xec\xaf\xcc\x5b\xc9\xb1\x52\xe6\x9d\x35\xef\xa2\x6f\x33\xbf\xcb\xfd\xe5\x80\x8c\x04\x17\xbe\x27\xc6\x0c\xef\x2f\xbf\xcd\xd7\xcf\x8c\xf1\xff\x37\x1f\x40\x58\x18\x4a\x2e\x6c\xa2\x68\xfe\xec\x03\x94\xda\xd3\xc1\xbe\x03\x65\xa2\xc5\xa6\xf4\x83\x61\x0f\x5b\x64\x08\x04\x45\xac\x68\x4f\x8c\x1d\x54\xb1\xfe\x44\x31\x24\xcd\x6d\xfd\xfa\xef\x55\xd9\x16\xad\x66\xbd\xea\x9d\xfd\xe7\xb5\x92\x83\x7b\x99\x67\x5f\x75\x77\x8f\x21\xff\xde\xfd\x9a\x16\xcd\xcd\x3a\xde\x2e\x4e\xfc\xc2\xf4\x74\x2b\x1c\x49\x4c\x1c\x1f\x5d\x0e\xad\xc0\xb9\x47\x31\xff\xc0\x01\xbc\x07\xbd\xcd\x88\xc0\x11\xb8\xc5\x39\x80\x3e\xdb\x4d\x75\x4a\x54\x78\x58\x99\xd8\x49\x8f\x5b\xed\x25\x47\x92\x4b\xad\xd5\x30\xe6\x8e\x40\x07\x5b\x56\xec\xb1\xa7\x48\x49\x3d\x33\x9d\xf7\xcc\x52\xd1\x3e\xbd\x6b\x4a\x19\x6c\x73\xec\x13\x3e\xeb\x12\xd6\x3d\xf3\xdd\xca\x3c\x49\xe5\xbb\xef\xc2\x8d\x68\xae\xfb\x75\xe7\x58\xc9\xf1\xfd\xd3\xce\xaa\x64\x59\x82\x8f\xcb\xf7\x9d\xb2\x4c\x91\x61\x33\x1e\x37\xf9\x71\x81\x57\x72\xfc\x3f\xe7\xdf\x00\x00\x00\xff\xff\x4c\xb1\xe6\xed\xff\x0c\x00\x00") func indexHtmlBytes() ([]byte, error) { return bindataRead( @@ -92,7 +92,7 @@ func indexHtml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "index.html", size: 3331, mode: os.FileMode(420), modTime: time.Unix(1573722179, 0)} + info := bindataFileInfo{name: "index.html", size: 3327, mode: os.FileMode(420), modTime: time.Unix(1573722179, 0)} a := &asset{bytes: bytes, info: info} return a, nil } diff --git a/templates/index.html b/templates/index.html index 03a41f07..f24d452f 100644 --- a/templates/index.html +++ b/templates/index.html @@ -71,7 +71,7 @@