Skip to content

Commit

Permalink
Merge pull request #33 from arashicage/agollo-with-accesskey
Browse files Browse the repository at this point in the history
agollo with access key secret
  • Loading branch information
shima-park authored Apr 23, 2020
2 parents a158c27 + bde5e2d commit 43e19ba
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 13 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
go.sum
.agollo
.idea
sandbox
2 changes: 2 additions & 0 deletions agollo.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ func NewWithConfigFile(configFilePath string, opts ...Option) (Agollo, error) {
Cluster string `json:"cluster,omitempty"`
NamespaceNames []string `json:"namespaceNames,omitempty"`
IP string `json:"ip,omitempty"`
AccessKey string `json:"accessKey,omitempty"`
}
if err := json.NewDecoder(f).Decode(&conf); err != nil {
return nil, err
Expand All @@ -89,6 +90,7 @@ func NewWithConfigFile(configFilePath string, opts ...Option) (Agollo, error) {
[]Option{
Cluster(conf.Cluster),
PreloadNamespaces(conf.NamespaceNames...),
AccessKey(conf.AccessKey),
},
opts...,
)...,
Expand Down
77 changes: 65 additions & 12 deletions apollo_client.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package agollo

import (
"crypto/hmac"
"crypto/sha1"
"encoding/base64"
"encoding/json"
"fmt"
"io/ioutil"
Expand Down Expand Up @@ -74,6 +77,7 @@ type apolloClient struct {
Doer Doer
IP string
ConfigType string // 默认properties不需要在namespace后加后缀名,其他情况例如application.json {xml,yml,yaml,json,...}
AccessKey string
}

type ApolloClientOption func(*apolloClient)
Expand All @@ -96,6 +100,12 @@ func WithConfigType(configType string) ApolloClientOption {
}
}

func WithAccessKey(accessKey string) ApolloClientOption {
return func(a *apolloClient) {
a.AccessKey = accessKey
}
}

func NewApolloClient(opts ...ApolloClientOption) ApolloClient {
c := &apolloClient{}
for _, opt := range opts {
Expand All @@ -119,16 +129,50 @@ func NewApolloClient(opts ...ApolloClientOption) ApolloClient {
return c
}

const (
AUTHORIZATION_FORMAT = "Apollo %s:%s"
DELIMITER = "\n"
HTTP_HEADER_AUTHORIZATION = "Authorization"
HTTP_HEADER_TIMESTAMP = "Timestamp"
)

func signature(timestamp, url, accessKey string) string {

stringToSign := timestamp + DELIMITER + url

key := []byte(accessKey)
mac := hmac.New(sha1.New, key)
mac.Write([]byte(stringToSign))
return base64.StdEncoding.EncodeToString(mac.Sum(nil))
}

func (c *apolloClient) httpHeader(appID, uri string) map[string]string {

headers := map[string]string{}
if "" == c.AccessKey {
return headers
}

timestamp := fmt.Sprintf("%v", time.Now().UnixNano()/int64(time.Millisecond))
signature := signature(timestamp, uri, c.AccessKey)

headers[HTTP_HEADER_AUTHORIZATION] = fmt.Sprintf(AUTHORIZATION_FORMAT, appID, signature)
headers[HTTP_HEADER_TIMESTAMP] = timestamp

return headers
}

func (c *apolloClient) Notifications(configServerURL, appID, cluster string, notifications []Notification) (status int, result []Notification, err error) {
configServerURL = normalizeURL(configServerURL)
url := fmt.Sprintf("%s/notifications/v2?appId=%s&cluster=%s&notifications=%s",
configServerURL,
requestURI := fmt.Sprintf("/notifications/v2?appId=%s&cluster=%s&notifications=%s",
url.QueryEscape(appID),
url.QueryEscape(cluster),
url.QueryEscape(Notifications(notifications).String()),
)
apiURL := fmt.Sprintf("%s%s", configServerURL, requestURI)

status, err = c.do("GET", url, &result)
headers := c.httpHeader(appID, requestURI)
status, err = c.do("GET", apiURL, headers, &result)
return
}

Expand All @@ -139,51 +183,60 @@ func (c *apolloClient) GetConfigsFromNonCache(configServerURL, appID, cluster, n
}

configServerURL = normalizeURL(configServerURL)
url := fmt.Sprintf("%s/configs/%s/%s/%s?releaseKey=%s&ip=%s",
configServerURL,
requestURI := fmt.Sprintf("/configs/%s/%s/%s?releaseKey=%s&ip=%s",
url.QueryEscape(appID),
url.QueryEscape(cluster),
url.QueryEscape(c.getNamespace(namespace)),
options.ReleaseKey,
c.IP,
)
apiURL := fmt.Sprintf("%s%s", configServerURL, requestURI)

headers := c.httpHeader(appID, requestURI)
config = new(Config)
status, err = c.do("GET", url, config)
status, err = c.do("GET", apiURL, headers, config)
return

}

func (c *apolloClient) GetConfigsFromCache(configServerURL, appID, cluster, namespace string) (config Configurations, err error) {
configServerURL = normalizeURL(configServerURL)
url := fmt.Sprintf("%s/configfiles/json/%s/%s/%s?ip=%s",
configServerURL,
requestURI := fmt.Sprintf("/configfiles/json/%s/%s/%s?ip=%s",
url.QueryEscape(appID),
url.QueryEscape(cluster),
url.QueryEscape(c.getNamespace(namespace)),
c.IP,
)
apiURL := fmt.Sprintf("%s%s", configServerURL, requestURI)

headers := c.httpHeader(appID, requestURI)
config = make(Configurations)
_, err = c.do("GET", url, config)
_, err = c.do("GET", apiURL, headers, config)
return
}

func (c *apolloClient) GetConfigServers(metaServerURL, appID string) (int, []ConfigServer, error) {
metaServerURL = normalizeURL(metaServerURL)
url := fmt.Sprintf("%s/services/config?id=%s&appId=%s", metaServerURL, c.IP, appID)
requestURI := fmt.Sprintf("/services/config?id=%s&appId=%s", c.IP, appID)
apiURL := fmt.Sprintf("%s%s", metaServerURL, requestURI)

headers := c.httpHeader(appID, requestURI)
var cfs []ConfigServer
status, err := c.do("GET", url, &cfs)
status, err := c.do("GET", apiURL, headers, &cfs)
return status, cfs, err
}

func (c *apolloClient) do(method, url string, v interface{}) (status int, err error) {
func (c *apolloClient) do(method, url string, headers map[string]string, v interface{}) (status int, err error) {
var req *http.Request
req, err = http.NewRequest(method, url, nil)
if err != nil {
return
}

for key, val := range headers {
req.Header.Set(key, val)
}

var body []byte
status, body, err = parseResponseBody(c.Doer, req)
if err != nil {
Expand Down
11 changes: 10 additions & 1 deletion options.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,15 @@ type Options struct {
Balancer Balancer // ConfigServer负载均衡
EnableSLB bool // 启用ConfigServer负载均衡
RefreshIntervalInSecond time.Duration // ConfigServer刷新间隔
AccessKey string
}

func newOptions(configServerURL, appID string, opts ...Option) (Options, error) {
var options = Options{
AppID: appID,
Cluster: defaultCluster,
DefaultNamespace: defaultNamespace,
ApolloClient: NewApolloClient(),
// ApolloClient: NewApolloClient(),
Logger: NewLogger(),
AutoFetchOnCacheMiss: defaultAutoFetchOnCacheMiss,
LongPollerInterval: defaultLongPollInterval,
Expand All @@ -48,6 +49,8 @@ func newOptions(configServerURL, appID string, opts ...Option) (Options, error)
opt(&options)
}

options.ApolloClient = NewApolloClient(WithAccessKey(options.AccessKey))

if options.Balancer == nil {
var b Balancer
configServerURLs := getConfigServers(configServerURL)
Expand Down Expand Up @@ -168,6 +171,12 @@ func ConfigServerRefreshIntervalInSecond(refreshIntervalInSecond time.Duration)
}
}

func AccessKey(accessKey string) Option {
return func(o *Options) {
o.AccessKey = accessKey
}
}

type GetOptions struct {
DefaultValue string
Namespace string
Expand Down

0 comments on commit 43e19ba

Please sign in to comment.