Skip to content

Commit a1229f0

Browse files
authored
Merge pull request #30 from solid-wang/master
feature: support license
2 parents 7e7d93a + 6b4d387 commit a1229f0

File tree

4 files changed

+133
-5
lines changed

4 files changed

+133
-5
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ GITHUBACTIONTRIGGERNUMBER = 12
55

66
REGISTRY = f5devcentral
77
NAME = ces-controller
8-
RELEASE_TAG = 0.6.0
8+
RELEASE_TAG = 0.6.1
99
COMMIT = git-$(shell git rev-parse --short HEAD)
1010
DATE = $(shell date +"%Y-%m-%d_%H:%M:%S")
1111
GOLDFLAGS = "-w -s -X github.com/kubeovn/$(NAME)/versions.COMMIT=$(COMMIT) -X github.com/kubeovn/$(NAME)/versions.VERSION=$(RELEASE_TAG) -X github.com/kubeovn/$(NAME)/versions.BUILDDATE=$(DATE)"

cmd/ces/main.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ var (
4646
bigipPassword string
4747
bigipCredsDir string
4848
bigipConfDir string
49+
50+
license string
51+
licenseKey string
4952
)
5053

5154
func main() {
@@ -56,6 +59,8 @@ func main() {
5659
if bigipCredsDir != "" {
5760
usernameFile := filepath.Join(bigipCredsDir, "username")
5861
passwordFile := filepath.Join(bigipCredsDir, "password")
62+
licenseFIle := filepath.Join(bigipCredsDir, "license")
63+
licenseKeyFile := filepath.Join(bigipCredsDir, "licensekey")
5964

6065
setField := func(field *string, filename, fieldType string) error {
6166
fileBytes, readErr := ioutil.ReadFile(filename)
@@ -77,6 +82,12 @@ func main() {
7782
if err := setField(&bigipPassword, passwordFile, "password"); err != nil {
7883
panic(err)
7984
}
85+
if err := setField(&license, licenseFIle, "license"); err != nil {
86+
panic(err)
87+
}
88+
if err := setField(&licenseKey, licenseKeyFile, "license key"); err != nil {
89+
panic(err)
90+
}
8091
}
8192

8293
if bigipUsername == "" || bigipPassword == "" {
@@ -111,6 +122,11 @@ func main() {
111122
klog.Fatal("env CES_NAMESPACE can't be empty ")
112123
}
113124
bigIpClient := as3.NewClient(bigipURL, bigipUsername, bigipPassword, bigipInsecure)
125+
126+
if err := bigIpClient.VerifyLicense(license, licenseKey); err != nil {
127+
klog.Fatalf("failed to verify license: %v", err)
128+
return
129+
}
114130
err = as3.InitAs3Tenant(bigIpClient, bigipConfDir, controllerNamespace)
115131
if err != nil {
116132
klog.Fatalf("failed to initialize AS3 declaration: %v", err)
@@ -154,6 +170,8 @@ func init() {
154170
flag.BoolVar(&bigipInsecure, "bigip-insecure", false, "Optional, when set to true, enable insecure SSL communication to BigIP.")
155171
flag.StringVar(&bigipUsername, "bigip-username", "", "User name for the Big-IP user account.")
156172
flag.StringVar(&bigipPassword, "bigip-password", "", "Password for the Big-IP user account.")
173+
flag.StringVar(&license, "license", "", "license to be used.")
174+
flag.StringVar(&licenseKey, "license-key", "", "license key to be used for ces license.")
157175
flag.StringVar(&bigipCredsDir, "bigip-creds-dir", "", "Directory that contains the BIG-IP username and password. To be used instead of username and password.")
158176
flag.StringVar(&bigipConfDir, "bigip-conf-dir", "", "Directory that ces-conf.yaml file.")
159177
}

dist/install.sh

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
#!/usr/bin/env bash
22
set -euo pipefail
33

4+
LICENSE=${LICENSE:-}
5+
LICENSEKEY=${LICENSEKEY:-}
6+
47
BIGIP_URL=${BIGIP_URL:-} # IP address of Big-IP server
58
BIGIP_USERNAME=${BIGIP_USERNAME:-} # BigIP username
69
BIGIP_PASSWORD=${BIGIP_PASSWORD:-} # BigIP password
@@ -10,7 +13,7 @@ CES_NAMESPACE=${CES_NAMESPACE:-kube-system} # namespace in which the controller
1013
CES_DEPLOMENT_NAME=${CES_DEPLOMENT_NAME:-ces-controller}
1114

1215
echo "[Step 1] Create Secret"
13-
kubectl -n $CES_NAMESPACE create secret generic --from-literal "username=$BIGIP_USERNAME" --from-literal "password=$BIGIP_PASSWORD" bigip-creds
16+
kubectl -n $CES_NAMESPACE create secret generic --from-literal "license=$LICENSE" --from-literal "licensekey=$LICENSEKEY" --from-literal "username=$BIGIP_USERNAME" --from-literal "password=$BIGIP_PASSWORD" bigip-creds
1417
echo "-------------------------------"
1518
echo ""
1619

@@ -532,7 +535,7 @@ spec:
532535
serviceAccountName: ces-controller
533536
containers:
534537
- name: ces-controller
535-
image: f5devcentral/ces-controller:0.6.0
538+
image: f5devcentral/ces-controller:0.6.1
536539
env:
537540
- name: CES_NAMESPACE
538541
value: $CES_NAMESPACE

pkg/as3/client.go

Lines changed: 109 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@ package as3
1818

1919
import (
2020
"bytes"
21+
"crypto/aes"
22+
"crypto/cipher"
2123
"crypto/tls"
24+
"encoding/base64"
2225
"encoding/json"
2326
"fmt"
2427
"io/ioutil"
@@ -117,11 +120,11 @@ func (c *Client) Get(partition string) (string, error) {
117120
return "", err
118121
}
119122
//Common tenant isn't exist, body is "" == (as3 do not set)
120-
if err == nil && resp.StatusCode > 199 && resp.StatusCode <299 && string(respBody) == ""{
123+
if err == nil && resp.StatusCode > 199 && resp.StatusCode < 299 && string(respBody) == "" {
121124
return "{}", nil
122125
}
123126
//specified Tenant(s) not found in declaration
124-
if resp.StatusCode == 404{
127+
if resp.StatusCode == 404 {
125128
return "{}", nil
126129
}
127130
var response map[string]interface{}
@@ -370,3 +373,107 @@ func (c *Client) storeDisk() error {
370373
}
371374
return handleResponse(resp.StatusCode, response)
372375
}
376+
377+
// get f5 license key
378+
func (c *Client) getF5LicenseKey() (string, error) {
379+
url := c.host + "/mgmt/tm/sys/license"
380+
req, err := http.NewRequest(http.MethodGet, url, nil)
381+
if err != nil {
382+
klog.Errorf("Failed to get bigdata license: %v", err)
383+
return "", err
384+
}
385+
req.SetBasicAuth(c.username, c.password)
386+
387+
resp, err := c.Do(req)
388+
if err != nil {
389+
klog.Errorf("Failed to call bigdata API: %v", err)
390+
return "", err
391+
}
392+
defer resp.Body.Close()
393+
394+
respBody, err := ioutil.ReadAll(resp.Body)
395+
if err != nil {
396+
klog.Errorf("Failed to read response body: %v", err)
397+
return "", err
398+
}
399+
400+
if resp.StatusCode != 200 && string(respBody) == "" {
401+
return "", fmt.Errorf("Failed to get license key")
402+
}
403+
404+
type RegistrationKey struct {
405+
Description string `json:"description"`
406+
}
407+
408+
type License struct {
409+
RegistrationKey RegistrationKey `json:"registrationKey"`
410+
}
411+
412+
type NestedStatsEntries struct {
413+
Entries License `json:"entries"`
414+
}
415+
416+
type LicentseNestedStats struct {
417+
NestedStats NestedStatsEntries `json:"nestedStats"`
418+
}
419+
420+
type LicentseZero struct {
421+
Zero LicentseNestedStats `json:"https://localhost/mgmt/tm/sys/license/0"`
422+
}
423+
424+
type BigDataLicense struct {
425+
Entries LicentseZero `json:"entries"`
426+
}
427+
428+
var license BigDataLicense
429+
if err = json.Unmarshal(respBody, &license); err != nil {
430+
klog.Errorf("Failed to unmarshal license body: %v", err)
431+
return "", err
432+
}
433+
return license.Entries.Zero.NestedStats.Entries.RegistrationKey.Description, nil
434+
}
435+
436+
// verify license, If err is nil, the verification passes.
437+
func (c *Client) VerifyLicense(license string, key string) error {
438+
bigDataLicense, err := c.getF5LicenseKey()
439+
if err != nil {
440+
return err
441+
}
442+
443+
bytesPass, err := base64.StdEncoding.DecodeString(license)
444+
if err != nil {
445+
return err
446+
}
447+
448+
tpass, err := AesDecrypt(bytesPass, []byte(key))
449+
if err != nil {
450+
return err
451+
}
452+
453+
if bigDataLicense != string(tpass) {
454+
return fmt.Errorf("license is not ok")
455+
}
456+
457+
return nil
458+
}
459+
460+
func PKCS5UnPadding(origData []byte) []byte {
461+
length := len(origData)
462+
unpadding := int(origData[length-1])
463+
return origData[:(length - unpadding)]
464+
}
465+
466+
func AesDecrypt(crypted, key []byte) ([]byte, error) {
467+
block, err := aes.NewCipher(key)
468+
if err != nil {
469+
return nil, err
470+
}
471+
472+
//AES分组长度为128位,所以blockSize=16,单位字节
473+
blockSize := block.BlockSize()
474+
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize]) //初始向量的长度必须等于块block的长度16字节
475+
origData := make([]byte, len(crypted))
476+
blockMode.CryptBlocks(origData, crypted)
477+
origData = PKCS5UnPadding(origData)
478+
return origData, nil
479+
}

0 commit comments

Comments
 (0)