check etag for etcd update and delete ops (#175)
This commit is contained in:
parent
1a37f892aa
commit
9323c44ecf
|
@ -9,9 +9,9 @@ import (
|
|||
"bytes"
|
||||
"encoding/json"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/aws/aws-sdk-go/service/s3/s3manager"
|
||||
"github.com/google/uuid"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
|
|
|
@ -11,11 +11,11 @@ import (
|
|||
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/aws/aws-sdk-go/service/sqs"
|
||||
"github.com/dapr/components-contrib/bindings"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// AWSSQS allows receiving and sending data to/from AWS SQS
|
||||
|
|
|
@ -14,8 +14,8 @@ import (
|
|||
"time"
|
||||
|
||||
eventhub "github.com/Azure/azure-event-hubs-go"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/dapr/components-contrib/bindings"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// AzureEventHubs allows sending/receiving Azure Event Hubs events
|
||||
|
|
|
@ -17,8 +17,8 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/Azure/azure-storage-queue-go/azqueue"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/dapr/components-contrib/bindings"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type consumer struct {
|
||||
|
@ -151,7 +151,6 @@ func (a *AzureStorageQueues) Write(req *bindings.WriteRequest) error {
|
|||
}
|
||||
|
||||
func (a *AzureStorageQueues) Read(handler func(*bindings.ReadResponse) error) error {
|
||||
|
||||
c := consumer{
|
||||
callback: handler,
|
||||
}
|
||||
|
|
|
@ -35,7 +35,6 @@ func (m *MockHelper) Read(ctx context.Context, consumer *consumer) error {
|
|||
}
|
||||
|
||||
func TestWriteQueue(t *testing.T) {
|
||||
|
||||
mm := new(MockHelper)
|
||||
mm.On("Init", mock.AnythingOfType("string"), mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(nil)
|
||||
|
||||
|
@ -158,11 +157,9 @@ func TestReadQueueNoMessage(t *testing.T) {
|
|||
pid := syscall.Getpid()
|
||||
proc, _ := os.FindProcess(pid)
|
||||
proc.Signal(os.Interrupt)
|
||||
|
||||
}
|
||||
|
||||
func TestParseMetadata(t *testing.T) {
|
||||
|
||||
m := bindings.Metadata{}
|
||||
m.Properties = map[string]string{"storageAccessKey": "myKey", "queue": "queue1", "storageAccount": "devstoreaccount1"}
|
||||
|
||||
|
|
|
@ -17,8 +17,8 @@ import (
|
|||
"syscall"
|
||||
|
||||
"github.com/Shopify/sarama"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/dapr/components-contrib/bindings"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Kafka allows reading/writing to a Kafka consumer group
|
||||
|
|
|
@ -1,116 +1,116 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
package oauth2
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
"context"
|
||||
|
||||
"github.com/dapr/components-contrib/middleware"
|
||||
"github.com/fasthttp-contrib/sessions"
|
||||
"github.com/google/uuid"
|
||||
"github.com/valyala/fasthttp"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
// Metadata is the oAuth middleware config
|
||||
type oAuth2MiddlewareMetadata struct {
|
||||
ClientID string `json:"clientID"`
|
||||
ClientSecret string `json:"clientSecret"`
|
||||
Scopes string `json:"scopes"`
|
||||
AuthURL string `json:"authURL"`
|
||||
TokenURL string `json:"tokenURL"`
|
||||
AuthHeaderName string `json:"authHeaderName"`
|
||||
RedirectURL string `json:"redirectURL"`
|
||||
}
|
||||
|
||||
// NewOAuth2Middleware returns a new oAuth2 middleware
|
||||
func NewOAuth2Middleware() *Middleware {
|
||||
return &Middleware{}
|
||||
}
|
||||
|
||||
// Middleware is an oAuth2 authentication middleware
|
||||
type Middleware struct {
|
||||
}
|
||||
|
||||
const (
|
||||
stateParam = "state"
|
||||
savedState = "auth-state"
|
||||
redirectPath = "redirect-url"
|
||||
codeParam = "code"
|
||||
)
|
||||
|
||||
// GetHandler retruns the HTTP handler provided by the middleware
|
||||
func (m *Middleware) GetHandler(metadata middleware.Metadata) (func(h fasthttp.RequestHandler) fasthttp.RequestHandler, error) {
|
||||
meta, err := m.getNativeMetadata(metadata)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return func(h fasthttp.RequestHandler) fasthttp.RequestHandler {
|
||||
return func(ctx *fasthttp.RequestCtx) {
|
||||
conf := &oauth2.Config{
|
||||
ClientID: meta.ClientID,
|
||||
ClientSecret: meta.ClientSecret,
|
||||
Scopes: strings.Split(meta.Scopes, ","),
|
||||
RedirectURL: meta.RedirectURL,
|
||||
Endpoint: oauth2.Endpoint{
|
||||
AuthURL: meta.AuthURL,
|
||||
TokenURL: meta.TokenURL,
|
||||
},
|
||||
}
|
||||
session := sessions.StartFasthttp(ctx)
|
||||
if session.GetString(meta.AuthHeaderName) != "" {
|
||||
ctx.Request.Header.Add(meta.AuthHeaderName, session.GetString(meta.AuthHeaderName))
|
||||
h(ctx)
|
||||
return
|
||||
}
|
||||
state := string(ctx.FormValue(stateParam))
|
||||
if state == "" {
|
||||
id, _ := uuid.NewUUID()
|
||||
session.Set(savedState, id.String())
|
||||
session.Set(redirectPath, string(ctx.RequestURI()))
|
||||
url := conf.AuthCodeURL(id.String(), oauth2.AccessTypeOffline)
|
||||
ctx.Redirect(url, 302)
|
||||
} else {
|
||||
authState := session.GetString(savedState)
|
||||
redirectURL := session.GetString(redirectPath)
|
||||
if state != authState {
|
||||
ctx.Error("invalid state", fasthttp.StatusBadRequest)
|
||||
} else {
|
||||
code := string(ctx.FormValue(codeParam))
|
||||
if code == "" {
|
||||
ctx.Error("code not found", fasthttp.StatusBadRequest)
|
||||
} else {
|
||||
token, err := conf.Exchange(context.Background(), code)
|
||||
if err != nil {
|
||||
ctx.Error(err.Error(), fasthttp.StatusInternalServerError)
|
||||
}
|
||||
session.Set(meta.AuthHeaderName, token.Type()+" "+token.AccessToken)
|
||||
ctx.Request.Header.Add(meta.AuthHeaderName, token.Type()+" "+token.AccessToken)
|
||||
ctx.Redirect(redirectURL, 302)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *Middleware) getNativeMetadata(metadata middleware.Metadata) (*oAuth2MiddlewareMetadata, error) {
|
||||
b, err := json.Marshal(metadata.Properties)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var middlewareMetadata oAuth2MiddlewareMetadata
|
||||
err = json.Unmarshal(b, &middlewareMetadata)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &middlewareMetadata, nil
|
||||
}
|
||||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
package oauth2
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
"context"
|
||||
|
||||
"github.com/dapr/components-contrib/middleware"
|
||||
"github.com/fasthttp-contrib/sessions"
|
||||
"github.com/google/uuid"
|
||||
"github.com/valyala/fasthttp"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
// Metadata is the oAuth middleware config
|
||||
type oAuth2MiddlewareMetadata struct {
|
||||
ClientID string `json:"clientID"`
|
||||
ClientSecret string `json:"clientSecret"`
|
||||
Scopes string `json:"scopes"`
|
||||
AuthURL string `json:"authURL"`
|
||||
TokenURL string `json:"tokenURL"`
|
||||
AuthHeaderName string `json:"authHeaderName"`
|
||||
RedirectURL string `json:"redirectURL"`
|
||||
}
|
||||
|
||||
// NewOAuth2Middleware returns a new oAuth2 middleware
|
||||
func NewOAuth2Middleware() *Middleware {
|
||||
return &Middleware{}
|
||||
}
|
||||
|
||||
// Middleware is an oAuth2 authentication middleware
|
||||
type Middleware struct {
|
||||
}
|
||||
|
||||
const (
|
||||
stateParam = "state"
|
||||
savedState = "auth-state"
|
||||
redirectPath = "redirect-url"
|
||||
codeParam = "code"
|
||||
)
|
||||
|
||||
// GetHandler retruns the HTTP handler provided by the middleware
|
||||
func (m *Middleware) GetHandler(metadata middleware.Metadata) (func(h fasthttp.RequestHandler) fasthttp.RequestHandler, error) {
|
||||
meta, err := m.getNativeMetadata(metadata)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return func(h fasthttp.RequestHandler) fasthttp.RequestHandler {
|
||||
return func(ctx *fasthttp.RequestCtx) {
|
||||
conf := &oauth2.Config{
|
||||
ClientID: meta.ClientID,
|
||||
ClientSecret: meta.ClientSecret,
|
||||
Scopes: strings.Split(meta.Scopes, ","),
|
||||
RedirectURL: meta.RedirectURL,
|
||||
Endpoint: oauth2.Endpoint{
|
||||
AuthURL: meta.AuthURL,
|
||||
TokenURL: meta.TokenURL,
|
||||
},
|
||||
}
|
||||
session := sessions.StartFasthttp(ctx)
|
||||
if session.GetString(meta.AuthHeaderName) != "" {
|
||||
ctx.Request.Header.Add(meta.AuthHeaderName, session.GetString(meta.AuthHeaderName))
|
||||
h(ctx)
|
||||
return
|
||||
}
|
||||
state := string(ctx.FormValue(stateParam))
|
||||
if state == "" {
|
||||
id, _ := uuid.NewUUID()
|
||||
session.Set(savedState, id.String())
|
||||
session.Set(redirectPath, string(ctx.RequestURI()))
|
||||
url := conf.AuthCodeURL(id.String(), oauth2.AccessTypeOffline)
|
||||
ctx.Redirect(url, 302)
|
||||
} else {
|
||||
authState := session.GetString(savedState)
|
||||
redirectURL := session.GetString(redirectPath)
|
||||
if state != authState {
|
||||
ctx.Error("invalid state", fasthttp.StatusBadRequest)
|
||||
} else {
|
||||
code := string(ctx.FormValue(codeParam))
|
||||
if code == "" {
|
||||
ctx.Error("code not found", fasthttp.StatusBadRequest)
|
||||
} else {
|
||||
token, err := conf.Exchange(context.Background(), code)
|
||||
if err != nil {
|
||||
ctx.Error(err.Error(), fasthttp.StatusInternalServerError)
|
||||
}
|
||||
session.Set(meta.AuthHeaderName, token.Type()+" "+token.AccessToken)
|
||||
ctx.Request.Header.Add(meta.AuthHeaderName, token.Type()+" "+token.AccessToken)
|
||||
ctx.Redirect(redirectURL, 302)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *Middleware) getNativeMetadata(metadata middleware.Metadata) (*oAuth2MiddlewareMetadata, error) {
|
||||
b, err := json.Marshal(metadata.Properties)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var middlewareMetadata oAuth2MiddlewareMetadata
|
||||
err = json.Unmarshal(b, &middlewareMetadata)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &middlewareMetadata, nil
|
||||
}
|
||||
|
|
|
@ -12,8 +12,8 @@ import (
|
|||
"time"
|
||||
|
||||
azservicebus "github.com/Azure/azure-service-bus-go"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/dapr/components-contrib/pubsub"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
|
@ -9,9 +9,9 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/dapr/components-contrib/pubsub"
|
||||
nats "github.com/nats-io/go-nats"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
|
@ -3,8 +3,8 @@ package rabbitmq
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/dapr/components-contrib/pubsub"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/streadway/amqp"
|
||||
)
|
||||
|
||||
|
|
|
@ -49,7 +49,6 @@ func NewCloudKMSSecretStore() secretstores.SecretStore {
|
|||
|
||||
// Init creates a cloudkmsClient
|
||||
func (c *cloudkmsSecretStore) Init(metadata secretstores.Metadata) error {
|
||||
|
||||
b, err := c.parseMetadata(metadata)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -130,7 +129,6 @@ func (c *cloudkmsSecretStore) getCipherTextFromSecretObject(gcpStorageBucket str
|
|||
}
|
||||
|
||||
func (c *cloudkmsSecretStore) decryptSymmetric(name string, ciphertext []byte) ([]byte, error) {
|
||||
|
||||
ctx := context.Background()
|
||||
// Build the request
|
||||
req := &kmspb.DecryptRequest{
|
||||
|
|
|
@ -145,9 +145,23 @@ func (r *ETCD) Get(req *state.GetRequest) (*state.GetResponse, error) {
|
|||
|
||||
// Delete performs a delete operation
|
||||
func (r *ETCD) Delete(req *state.DeleteRequest) error {
|
||||
err := state.CheckDeleteRequestOptions(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx, cancelFn := context.WithTimeout(context.Background(), r.operationTimeout)
|
||||
defer cancelFn()
|
||||
_, err := r.client.Delete(ctx, req.Key)
|
||||
|
||||
version := req.ETag
|
||||
//honor client etag
|
||||
if version != "" {
|
||||
txn := r.client.KV.Txn(ctx)
|
||||
_, err = txn.If(clientv3.Compare(clientv3.Version(req.Key), "=", version)).Then(clientv3.OpDelete(req.Key)).Commit()
|
||||
} else {
|
||||
_, err = r.client.Delete(ctx, req.Key)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -169,6 +183,10 @@ func (r *ETCD) BulkDelete(req []state.DeleteRequest) error {
|
|||
|
||||
// Set saves state into ETCD
|
||||
func (r *ETCD) Set(req *state.SetRequest) error {
|
||||
err := state.CheckSetRequestOptions(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ctx, cancelFn := context.WithTimeout(context.Background(), r.operationTimeout)
|
||||
defer cancelFn()
|
||||
var vStr string
|
||||
|
@ -179,7 +197,15 @@ func (r *ETCD) Set(req *state.SetRequest) error {
|
|||
vStr, _ = r.json.MarshalToString(req.Value)
|
||||
}
|
||||
|
||||
_, err := r.client.Put(ctx, req.Key, vStr)
|
||||
version := req.ETag
|
||||
//honor client etag
|
||||
if version != "" {
|
||||
txn := r.client.KV.Txn(ctx)
|
||||
_, err = txn.If(clientv3.Compare(clientv3.Version(req.Key), "=", version)).Then(clientv3.OpPut(req.Key, vStr)).Commit()
|
||||
} else {
|
||||
_, err = r.client.Put(ctx, req.Key, vStr)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue