From 093bfee31b374539014de625c9ca1bfbd1831d3b Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Wed, 18 Mar 2020 10:30:18 +0100 Subject: [PATCH 01/39] add basic gitignore --- .gitignore | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..192669f97e --- /dev/null +++ b/.gitignore @@ -0,0 +1,23 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, build with `go test -c` +*.test + +# Coverage +coverage.txt + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +#Debug +__debug_bin +debug + +# IDE +.idea +.vscode \ No newline at end of file From 5b1d6a6cf8b0f3d4fa0303b1843fb12b2975908e Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Wed, 18 Mar 2020 10:38:32 +0100 Subject: [PATCH 02/39] init go mod --- go.mod | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 go.mod diff --git a/go.mod b/go.mod new file mode 100644 index 0000000000..688cb8fc60 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module github.com/caos/zitadel + +go 1.14 From f8fdbb06113a8ed99e7bdb8958a09e6e43818229 Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Wed, 18 Mar 2020 11:39:48 +0100 Subject: [PATCH 03/39] add semrel and badges --- .releaserc.js | 11 +++++++++++ README.md | 8 +++++++- 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 .releaserc.js diff --git a/.releaserc.js b/.releaserc.js new file mode 100644 index 0000000000..ec7652c00e --- /dev/null +++ b/.releaserc.js @@ -0,0 +1,11 @@ +module.exports = { + branch: 'master', + plugins: [ + "@semantic-release/commit-analyzer", + "@semantic-release/release-notes-generator", + "@semantic-release/github", + ["@semantic-release/exec", { + "prepareCmd": "echo '::set-env name=CAOS_NEXT_VERSION::v${nextRelease.version}'" + }], + ] +}; \ No newline at end of file diff --git a/README.md b/README.md index d5cd7681a3..546361b2d9 100644 --- a/README.md +++ b/README.md @@ -1 +1,7 @@ -# zitadel \ No newline at end of file +# zitadel + +![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg) +![Release Badge](https://github.com/caos/zitadel/workflows/Test,%20Build,%20Release/badge.svg) +[![GitHub license](https://img.shields.io/github/license/caos/zitadel)](https://github.com/caos/zitadel/blob/master/LICENSE) +[![GitHub release](https://img.shields.io/github/release/caos/zitadel)](https://github.com/caos/zitadel/releases/) + From 238347ddfb30162fd97e0e61e3e0ae3774102418 Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Wed, 18 Mar 2020 15:45:24 +0100 Subject: [PATCH 04/39] add error pkg --- internal/errors/already_exists.go | 32 ++++++++ internal/errors/already_exists_test.go | 34 +++++++++ internal/errors/caos_error.go | 48 ++++++++++++ internal/errors/caos_error_test.go | 19 +++++ internal/errors/deadline_exceeded.go | 34 +++++++++ internal/errors/deadline_exceeded_test.go | 33 ++++++++ internal/errors/error.go | 18 +++++ internal/errors/error_test.go | 19 +++++ internal/errors/generate/error.go.tmpl | 34 +++++++++ internal/errors/generate/error_creator.go | 75 +++++++++++++++++++ .../errors/generate/error_interface.go.tmpl | 5 ++ internal/errors/generate/error_test.go.tmpl | 33 ++++++++ internal/errors/internal.go | 34 +++++++++ internal/errors/internal_test.go | 33 ++++++++ internal/errors/invalid_argument.go | 32 ++++++++ internal/errors/invalid_argument_test.go | 33 ++++++++ internal/errors/not_found.go | 27 +++++++ internal/errors/not_found_test.go | 33 ++++++++ internal/errors/permission_denied.go | 34 +++++++++ internal/errors/permission_denied_test.go | 33 ++++++++ internal/errors/precondition_failed.go | 34 +++++++++ internal/errors/precondition_failed_test.go | 33 ++++++++ internal/errors/unauthenticated.go | 34 +++++++++ internal/errors/unauthenticated_test.go | 33 ++++++++ internal/errors/unavailable.go | 34 +++++++++ internal/errors/unavailable_test.go | 33 ++++++++ internal/errors/unimplemented.go | 34 +++++++++ internal/errors/unimplemented_test.go | 33 ++++++++ internal/errors/unknown.go | 34 +++++++++ internal/errors/unknown_test.go | 33 ++++++++ 30 files changed, 978 insertions(+) create mode 100644 internal/errors/already_exists.go create mode 100644 internal/errors/already_exists_test.go create mode 100644 internal/errors/caos_error.go create mode 100644 internal/errors/caos_error_test.go create mode 100644 internal/errors/deadline_exceeded.go create mode 100644 internal/errors/deadline_exceeded_test.go create mode 100644 internal/errors/error.go create mode 100644 internal/errors/error_test.go create mode 100644 internal/errors/generate/error.go.tmpl create mode 100644 internal/errors/generate/error_creator.go create mode 100644 internal/errors/generate/error_interface.go.tmpl create mode 100644 internal/errors/generate/error_test.go.tmpl create mode 100644 internal/errors/internal.go create mode 100644 internal/errors/internal_test.go create mode 100644 internal/errors/invalid_argument.go create mode 100644 internal/errors/invalid_argument_test.go create mode 100644 internal/errors/not_found.go create mode 100644 internal/errors/not_found_test.go create mode 100644 internal/errors/permission_denied.go create mode 100644 internal/errors/permission_denied_test.go create mode 100644 internal/errors/precondition_failed.go create mode 100644 internal/errors/precondition_failed_test.go create mode 100644 internal/errors/unauthenticated.go create mode 100644 internal/errors/unauthenticated_test.go create mode 100644 internal/errors/unavailable.go create mode 100644 internal/errors/unavailable_test.go create mode 100644 internal/errors/unimplemented.go create mode 100644 internal/errors/unimplemented_test.go create mode 100644 internal/errors/unknown.go create mode 100644 internal/errors/unknown_test.go diff --git a/internal/errors/already_exists.go b/internal/errors/already_exists.go new file mode 100644 index 0000000000..17720298dc --- /dev/null +++ b/internal/errors/already_exists.go @@ -0,0 +1,32 @@ +package errors + +import "fmt" + +var ( + _ AlreadyExists = (*AlreadyExistsError)(nil) + _ Error = (*AlreadyExistsError)(nil) +) + +type AlreadyExists interface { + error + IsAlreadyExists() +} + +type AlreadyExistsError struct { + *CaosError +} + +func ThrowAlreadyExists(parent error, id, message string) error { + return &AlreadyExistsError{createCaosError(parent, id, message)} +} + +func ThrowAlreadyExistsf(parent error, id, format string, a ...interface{}) error { + return &AlreadyExistsError{createCaosError(parent, id, fmt.Sprintf(format, a...))} +} + +func (err *AlreadyExistsError) IsAlreadyExists() {} + +func IsErrorAlreadyExists(err error) bool { + _, ok := err.(AlreadyExists) + return ok +} diff --git a/internal/errors/already_exists_test.go b/internal/errors/already_exists_test.go new file mode 100644 index 0000000000..b239e777ba --- /dev/null +++ b/internal/errors/already_exists_test.go @@ -0,0 +1,34 @@ +package errors_test + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/assert" + + caos_errs "github.com/caos/utils/errors" +) + +func TestAlreadyExistsError(t *testing.T) { + var alreadyExistsError interface{} + alreadyExistsError = new(caos_errs.AlreadyExistsError) + _, ok := alreadyExistsError.(caos_errs.AlreadyExists) + assert.True(t, ok) +} + +func TestThrowAlreadyExistsf(t *testing.T) { + err := caos_errs.ThrowAlreadyExistsf(nil, "id", "msg") + + _, ok := err.(*caos_errs.AlreadyExistsError) + assert.True(t, ok) +} + +func TestIsErrorAlreadyExists(t *testing.T) { + err := caos_errs.ThrowAlreadyExists(nil, "id", "msg") + ok := caos_errs.IsErrorAlreadyExists(err) + assert.True(t, ok) + + err = errors.New("Already Exists!") + ok = caos_errs.IsErrorAlreadyExists(err) + assert.False(t, ok) +} diff --git a/internal/errors/caos_error.go b/internal/errors/caos_error.go new file mode 100644 index 0000000000..4788b501ee --- /dev/null +++ b/internal/errors/caos_error.go @@ -0,0 +1,48 @@ +package errors + +import ( + "fmt" +) + +var _ Error = (*CaosError)(nil) + +type CaosError struct { + Parent error + Message string + ID string +} + +func ThrowError(parent error, id, message string) error { + return createCaosError(parent, id, message) +} + +func createCaosError(parent error, id, message string) *CaosError { + return &CaosError{ + Parent: parent, + ID: id, + Message: message, + } +} + +func (err *CaosError) Error() string { + if err.Parent != nil { + return fmt.Sprintf("ID=%s Message=%s Parent=(%v)", err.ID, err.Message, err.Parent) + } + return fmt.Sprintf("ID=%s Message=%s", err.ID, err.Message) +} + +func (err *CaosError) Unwrap() error { + return err.GetParent() +} + +func (err *CaosError) GetParent() error { + return err.Parent +} + +func (err *CaosError) GetMessage() string { + return err.Message +} + +func (err *CaosError) GetID() string { + return err.ID +} diff --git a/internal/errors/caos_error_test.go b/internal/errors/caos_error_test.go new file mode 100644 index 0000000000..ce332ca361 --- /dev/null +++ b/internal/errors/caos_error_test.go @@ -0,0 +1,19 @@ +package errors_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + caos_errs "github.com/caos/utils/errors" +) + +func TestErrorMethod(t *testing.T) { + err := caos_errs.ThrowError(nil, "id", "msg") + expected := "ID=id Message=msg" + assert.Equal(t, expected, err.Error()) + + err = caos_errs.ThrowError(err, "subID", "subMsg") + subExptected := "ID=subID Message=subMsg Parent=(ID=id Message=msg)" + assert.Equal(t, subExptected, err.Error()) +} diff --git a/internal/errors/deadline_exceeded.go b/internal/errors/deadline_exceeded.go new file mode 100644 index 0000000000..b2a9a31b8e --- /dev/null +++ b/internal/errors/deadline_exceeded.go @@ -0,0 +1,34 @@ +package errors + +import ( + "fmt" +) + +var ( + _ DeadlineExceeded = (*DeadlineExceededError)(nil) + _ Error = (*DeadlineExceededError)(nil) +) + +type DeadlineExceeded interface { + error + IsDeadlineExceeded() +} + +type DeadlineExceededError struct { + *CaosError +} + +func ThrowDeadlineExceeded(parent error, id, message string) error { + return &DeadlineExceededError{createCaosError(parent, id, message)} +} + +func ThrowDeadlineExceededf(parent error, id, format string, a ...interface{}) error { + return ThrowDeadlineExceeded(parent, id, fmt.Sprintf(format, a...)) +} + +func (err *DeadlineExceededError) IsDeadlineExceeded() {} + +func IsDeadlineExceeded(err error) bool { + _, ok := err.(DeadlineExceeded) + return ok +} diff --git a/internal/errors/deadline_exceeded_test.go b/internal/errors/deadline_exceeded_test.go new file mode 100644 index 0000000000..0758d6041e --- /dev/null +++ b/internal/errors/deadline_exceeded_test.go @@ -0,0 +1,33 @@ +package errors_test + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/assert" + + caos_errs "github.com/caos/utils/errors" +) + +func TestDeadlineExceededError(t *testing.T) { + var err interface{} + err = new(caos_errs.DeadlineExceededError) + _, ok := err.(caos_errs.DeadlineExceeded) + assert.True(t, ok) +} + +func TestThrowDeadlineExceededf(t *testing.T) { + err := caos_errs.ThrowDeadlineExceededf(nil, "id", "msg") + _, ok := err.(*caos_errs.DeadlineExceededError) + assert.True(t, ok) +} + +func TestIsDeadlineExceeded(t *testing.T) { + err := caos_errs.ThrowDeadlineExceeded(nil, "id", "msg") + ok := caos_errs.IsDeadlineExceeded(err) + assert.True(t, ok) + + err = errors.New("I am found!") + ok = caos_errs.IsDeadlineExceeded(err) + assert.False(t, ok) +} diff --git a/internal/errors/error.go b/internal/errors/error.go new file mode 100644 index 0000000000..7e25b0ed39 --- /dev/null +++ b/internal/errors/error.go @@ -0,0 +1,18 @@ +package errors + +import ( + "strings" +) + +// Error is a stdlib error extension. +// It contains parameters to identify errors through all application layers +type Error interface { + GetParent() error + GetMessage() string + GetID() string +} + +// Contains compares the error message with needle +func Contains(err error, needle string) bool { + return err != nil && strings.Contains(err.Error(), needle) +} diff --git a/internal/errors/error_test.go b/internal/errors/error_test.go new file mode 100644 index 0000000000..da822d45ed --- /dev/null +++ b/internal/errors/error_test.go @@ -0,0 +1,19 @@ +package errors_test + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/assert" + + caos_errors "github.com/caos/utils/errors" +) + +func TestContains(t *testing.T) { + err := errors.New("hello world") + world := caos_errors.Contains(err, "hello") + assert.True(t, world) + + mars := caos_errors.Contains(err, "mars") + assert.False(t, mars) +} diff --git a/internal/errors/generate/error.go.tmpl b/internal/errors/generate/error.go.tmpl new file mode 100644 index 0000000000..f41e99ff9c --- /dev/null +++ b/internal/errors/generate/error.go.tmpl @@ -0,0 +1,34 @@ +package errors + +import ( + "fmt" +) + +var ( + _ {{.ErrorName}} = (*{{.ErrorName}}Error)(nil) + _ Error = (*{{.ErrorName}}Error)(nil) +) + +type {{.ErrorName}} interface { + error + Is{{.ErrorName}}() +} + +type {{.ErrorName}}Error struct { + *CaosError +} + +func Throw{{.ErrorName}}(parent error, id, message string) error { + return &{{.ErrorName}}Error{createCaosError(parent, id, message)} +} + +func Throw{{.ErrorName}}f(parent error, id, format string, a ...interface{}) error { + return Throw{{.ErrorName}}(parent, id, fmt.Sprintf(format, a...)) +} + +func (err *{{.ErrorName}}Error) Is{{.ErrorName}}() {} + +func Is{{.ErrorName}}(err error) bool { + _, ok := err.({{.ErrorName}}) + return ok +} diff --git a/internal/errors/generate/error_creator.go b/internal/errors/generate/error_creator.go new file mode 100644 index 0000000000..02a5538136 --- /dev/null +++ b/internal/errors/generate/error_creator.go @@ -0,0 +1,75 @@ +//go generate +package main + +import ( + "flag" + "fmt" + "html/template" + "log" + "os" + "strings" +) + +func main() { + errorName := readErrorName() + errorName = validateErrorName(errorName) + + data := &Data{ + ErrorName: errorName, + } + + errorFile := data.createFile("error.go.tmpl") + data.createTemplate("error.go.tmpl", errorFile) + if err := errorFile.Close(); err != nil { + log.Fatal(err) + } + + testFile := data.createFile("error_test.go.tmpl") + data.createTemplate("error_test.go.tmpl", testFile) + if err := testFile.Close(); err != nil { + log.Fatal(err) + } + + fmt.Print(` +!!!!! + Add status mapping in grpc/errors/caos_errors.go +!!!!!`) +} + +type Data struct { + ErrorName string +} + +func (data *Data) createFile(tmplName string) *os.File { + filename := strings.Replace(tmplName, "error", strings.ToLower(data.ErrorName), 1) + filename = filename[:len(filename)-5] + filePath := fmt.Sprintf("../%s", filename) + file, err := os.Create(filePath) + if err != nil { + log.Fatalf("unable to create file (%s): %v", filePath, err) + } + return file +} + +func (data *Data) createTemplate(templateName string, file *os.File) { + tmpl := template.Must(template.New(templateName).ParseFiles(templateName)) + if err := tmpl.Execute(file, data); err != nil { + log.Fatal("unable to execute tmpl: ", err) + } +} + +func readErrorName() (errorName string) { + flag.StringVar(&errorName, "Name", "", "Type of the error (e.g. Internal)") + flag.Parse() + return errorName +} + +func validateErrorName(errorName string) string { + if errorName == "" { + log.Fatal("pass argument name") + } + if strings.Contains(errorName, " ") || strings.Contains(errorName, ".") { + log.Fatal("name cannot contain spaces or points") + } + return strings.Title(errorName) +} diff --git a/internal/errors/generate/error_interface.go.tmpl b/internal/errors/generate/error_interface.go.tmpl new file mode 100644 index 0000000000..d67979b96e --- /dev/null +++ b/internal/errors/generate/error_interface.go.tmpl @@ -0,0 +1,5 @@ + +type {{.ErrorName}} interface { + error + Is{{.ErrorName}}() +} diff --git a/internal/errors/generate/error_test.go.tmpl b/internal/errors/generate/error_test.go.tmpl new file mode 100644 index 0000000000..6888001250 --- /dev/null +++ b/internal/errors/generate/error_test.go.tmpl @@ -0,0 +1,33 @@ +package errors_test + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/assert" + + caos_errs "github.com/caos/utils/errors" +) + +func Test{{.ErrorName}}Error(t *testing.T) { + var err interface{} + err = new(caos_errs.{{.ErrorName}}Error) + _, ok := err.(caos_errs.{{.ErrorName}}) + assert.True(t, ok) +} + +func TestThrow{{.ErrorName}}f(t *testing.T) { + err := caos_errs.Throw{{.ErrorName}}f(nil, "id", "msg") + _, ok := err.(*caos_errs.{{.ErrorName}}Error) + assert.True(t, ok) +} + +func TestIs{{.ErrorName}}(t *testing.T) { + err := caos_errs.Throw{{.ErrorName}}(nil, "id", "msg") + ok := caos_errs.Is{{.ErrorName}}(err) + assert.True(t, ok) + + err = errors.New("I am found!") + ok = caos_errs.Is{{.ErrorName}}(err) + assert.False(t, ok) +} diff --git a/internal/errors/internal.go b/internal/errors/internal.go new file mode 100644 index 0000000000..3f5a2c91d5 --- /dev/null +++ b/internal/errors/internal.go @@ -0,0 +1,34 @@ +package errors + +import ( + "fmt" +) + +var ( + _ Internal = (*InternalError)(nil) + _ Error = (*InternalError)(nil) +) + +type Internal interface { + error + IsInternal() +} + +type InternalError struct { + *CaosError +} + +func ThrowInternal(parent error, id, message string) error { + return &InternalError{createCaosError(parent, id, message)} +} + +func ThrowInternalf(parent error, id, format string, a ...interface{}) error { + return ThrowInternal(parent, id, fmt.Sprintf(format, a...)) +} + +func (err *InternalError) IsInternal() {} + +func IsInternal(err error) bool { + _, ok := err.(Internal) + return ok +} diff --git a/internal/errors/internal_test.go b/internal/errors/internal_test.go new file mode 100644 index 0000000000..b6ceb6e43f --- /dev/null +++ b/internal/errors/internal_test.go @@ -0,0 +1,33 @@ +package errors_test + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/assert" + + caos_errs "github.com/caos/utils/errors" +) + +func TestInternalError(t *testing.T) { + var err interface{} + err = new(caos_errs.InternalError) + _, ok := err.(caos_errs.Internal) + assert.True(t, ok) +} + +func TestThrowInternalf(t *testing.T) { + err := caos_errs.ThrowInternalf(nil, "id", "msg") + _, ok := err.(*caos_errs.InternalError) + assert.True(t, ok) +} + +func TestIsInternal(t *testing.T) { + err := caos_errs.ThrowInternal(nil, "id", "msg") + ok := caos_errs.IsInternal(err) + assert.True(t, ok) + + err = errors.New("I am found!") + ok = caos_errs.IsInternal(err) + assert.False(t, ok) +} diff --git a/internal/errors/invalid_argument.go b/internal/errors/invalid_argument.go new file mode 100644 index 0000000000..ab3eee5ae0 --- /dev/null +++ b/internal/errors/invalid_argument.go @@ -0,0 +1,32 @@ +package errors + +import "fmt" + +var ( + _ InvalidArgument = (*InvalidArgumentError)(nil) + _ Error = (*InvalidArgumentError)(nil) +) + +type InvalidArgument interface { + error + IsInvalidArgument() +} + +type InvalidArgumentError struct { + *CaosError +} + +func ThrowInvalidArgument(parent error, id, message string) error { + return &InvalidArgumentError{createCaosError(parent, id, message)} +} + +func ThrowInvalidArgumentf(parent error, id, format string, a ...interface{}) error { + return ThrowInvalidArgument(parent, id, fmt.Sprintf(format, a...)) +} + +func (err *InvalidArgumentError) IsInvalidArgument() {} + +func IsErrorInvalidArgument(err error) bool { + _, ok := err.(InvalidArgument) + return ok +} diff --git a/internal/errors/invalid_argument_test.go b/internal/errors/invalid_argument_test.go new file mode 100644 index 0000000000..ca635eaaf4 --- /dev/null +++ b/internal/errors/invalid_argument_test.go @@ -0,0 +1,33 @@ +package errors_test + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/assert" + + caos_errs "github.com/caos/utils/errors" +) + +func TestInvalidArgumentError(t *testing.T) { + var invalidArgumentError interface{} + invalidArgumentError = new(caos_errs.InvalidArgumentError) + _, ok := invalidArgumentError.(caos_errs.InvalidArgument) + assert.True(t, ok) +} + +func TestThrowInvalidArgumentf(t *testing.T) { + err := caos_errs.ThrowInvalidArgumentf(nil, "id", "msg") + _, ok := err.(*caos_errs.InvalidArgumentError) + assert.True(t, ok) +} + +func TestIsErrorInvalidArgument(t *testing.T) { + err := caos_errs.ThrowInvalidArgument(nil, "id", "msg") + ok := caos_errs.IsErrorInvalidArgument(err) + assert.True(t, ok) + + err = errors.New("I am invalid!") + ok = caos_errs.IsErrorInvalidArgument(err) + assert.False(t, ok) +} diff --git a/internal/errors/not_found.go b/internal/errors/not_found.go new file mode 100644 index 0000000000..fa988d0b69 --- /dev/null +++ b/internal/errors/not_found.go @@ -0,0 +1,27 @@ +package errors + +import "fmt" + +type NotFound interface { + error + IsNotFound() +} + +type NotFoundError struct { + *CaosError +} + +func ThrowNotFound(parent error, id, message string) error { + return &NotFoundError{createCaosError(parent, id, message)} +} + +func ThrowNotFoundf(parent error, id, format string, a ...interface{}) error { + return ThrowNotFound(parent, id, fmt.Sprintf(format, a...)) +} + +func (err *NotFoundError) IsNotFound() {} + +func IsNotFound(err error) bool { + _, ok := err.(NotFound) + return ok +} diff --git a/internal/errors/not_found_test.go b/internal/errors/not_found_test.go new file mode 100644 index 0000000000..8c3b5e383a --- /dev/null +++ b/internal/errors/not_found_test.go @@ -0,0 +1,33 @@ +package errors_test + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/assert" + + caos_errs "github.com/caos/utils/errors" +) + +func TestNotFoundError(t *testing.T) { + var notFoundError interface{} + notFoundError = new(caos_errs.NotFoundError) + _, ok := notFoundError.(caos_errs.NotFound) + assert.True(t, ok) +} + +func TestThrowNotFoundf(t *testing.T) { + err := caos_errs.ThrowNotFoundf(nil, "id", "msg") + _, ok := err.(*caos_errs.NotFoundError) + assert.True(t, ok) +} + +func TestIsNotFound(t *testing.T) { + err := caos_errs.ThrowNotFound(nil, "id", "msg") + ok := caos_errs.IsNotFound(err) + assert.True(t, ok) + + err = errors.New("I am found!") + ok = caos_errs.IsNotFound(err) + assert.False(t, ok) +} diff --git a/internal/errors/permission_denied.go b/internal/errors/permission_denied.go new file mode 100644 index 0000000000..b6900ee097 --- /dev/null +++ b/internal/errors/permission_denied.go @@ -0,0 +1,34 @@ +package errors + +import ( + "fmt" +) + +var ( + _ PermissionDenied = (*PermissionDeniedError)(nil) + _ Error = (*PermissionDeniedError)(nil) +) + +type PermissionDenied interface { + error + IsPermissionDenied() +} + +type PermissionDeniedError struct { + *CaosError +} + +func ThrowPermissionDenied(parent error, id, message string) error { + return &PermissionDeniedError{createCaosError(parent, id, message)} +} + +func ThrowPermissionDeniedf(parent error, id, format string, a ...interface{}) error { + return ThrowPermissionDenied(parent, id, fmt.Sprintf(format, a...)) +} + +func (err *PermissionDeniedError) IsPermissionDenied() {} + +func IsPermissionDenied(err error) bool { + _, ok := err.(PermissionDenied) + return ok +} diff --git a/internal/errors/permission_denied_test.go b/internal/errors/permission_denied_test.go new file mode 100644 index 0000000000..e7fbf0f96c --- /dev/null +++ b/internal/errors/permission_denied_test.go @@ -0,0 +1,33 @@ +package errors_test + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/assert" + + caos_errs "github.com/caos/utils/errors" +) + +func TestPermissionDeniedError(t *testing.T) { + var err interface{} + err = new(caos_errs.PermissionDeniedError) + _, ok := err.(caos_errs.PermissionDenied) + assert.True(t, ok) +} + +func TestThrowPermissionDeniedf(t *testing.T) { + err := caos_errs.ThrowPermissionDeniedf(nil, "id", "msg") + _, ok := err.(*caos_errs.PermissionDeniedError) + assert.True(t, ok) +} + +func TestIsPermissionDenied(t *testing.T) { + err := caos_errs.ThrowPermissionDenied(nil, "id", "msg") + ok := caos_errs.IsPermissionDenied(err) + assert.True(t, ok) + + err = errors.New("I am found!") + ok = caos_errs.IsPermissionDenied(err) + assert.False(t, ok) +} diff --git a/internal/errors/precondition_failed.go b/internal/errors/precondition_failed.go new file mode 100644 index 0000000000..a789de9968 --- /dev/null +++ b/internal/errors/precondition_failed.go @@ -0,0 +1,34 @@ +package errors + +import ( + "fmt" +) + +var ( + _ PreconditionFailed = (*PreconditionFailedError)(nil) + _ Error = (*PreconditionFailedError)(nil) +) + +type PreconditionFailed interface { + error + IsPreconditionFailed() +} + +type PreconditionFailedError struct { + *CaosError +} + +func ThrowPreconditionFailed(parent error, id, message string) error { + return &PreconditionFailedError{createCaosError(parent, id, message)} +} + +func ThrowPreconditionFailedf(parent error, id, format string, a ...interface{}) error { + return ThrowPreconditionFailed(parent, id, fmt.Sprintf(format, a...)) +} + +func (err *PreconditionFailedError) IsPreconditionFailed() {} + +func IsPreconditionFailed(err error) bool { + _, ok := err.(PreconditionFailed) + return ok +} diff --git a/internal/errors/precondition_failed_test.go b/internal/errors/precondition_failed_test.go new file mode 100644 index 0000000000..7fc3e50dd9 --- /dev/null +++ b/internal/errors/precondition_failed_test.go @@ -0,0 +1,33 @@ +package errors_test + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/assert" + + caos_errs "github.com/caos/utils/errors" +) + +func TestPreconditionFailedError(t *testing.T) { + var err interface{} + err = new(caos_errs.PreconditionFailedError) + _, ok := err.(caos_errs.PreconditionFailed) + assert.True(t, ok) +} + +func TestThrowPreconditionFailedf(t *testing.T) { + err := caos_errs.ThrowPreconditionFailedf(nil, "id", "msg") + _, ok := err.(*caos_errs.PreconditionFailedError) + assert.True(t, ok) +} + +func TestIsPreconditionFailed(t *testing.T) { + err := caos_errs.ThrowPreconditionFailed(nil, "id", "msg") + ok := caos_errs.IsPreconditionFailed(err) + assert.True(t, ok) + + err = errors.New("Precondition failed!") + ok = caos_errs.IsPreconditionFailed(err) + assert.False(t, ok) +} diff --git a/internal/errors/unauthenticated.go b/internal/errors/unauthenticated.go new file mode 100644 index 0000000000..fa1984ec5d --- /dev/null +++ b/internal/errors/unauthenticated.go @@ -0,0 +1,34 @@ +package errors + +import ( + "fmt" +) + +var ( + _ Unauthenticated = (*UnauthenticatedError)(nil) + _ Error = (*UnauthenticatedError)(nil) +) + +type Unauthenticated interface { + error + IsUnauthenticated() +} + +type UnauthenticatedError struct { + *CaosError +} + +func ThrowUnauthenticated(parent error, id, message string) error { + return &UnauthenticatedError{createCaosError(parent, id, message)} +} + +func ThrowUnauthenticatedf(parent error, id, format string, a ...interface{}) error { + return ThrowUnauthenticated(parent, id, fmt.Sprintf(format, a...)) +} + +func (err *UnauthenticatedError) IsUnauthenticated() {} + +func IsUnauthenticated(err error) bool { + _, ok := err.(Unauthenticated) + return ok +} diff --git a/internal/errors/unauthenticated_test.go b/internal/errors/unauthenticated_test.go new file mode 100644 index 0000000000..b64fd5f87b --- /dev/null +++ b/internal/errors/unauthenticated_test.go @@ -0,0 +1,33 @@ +package errors_test + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/assert" + + caos_errs "github.com/caos/utils/errors" +) + +func TestUnauthenticatedError(t *testing.T) { + var err interface{} + err = new(caos_errs.UnauthenticatedError) + _, ok := err.(caos_errs.Unauthenticated) + assert.True(t, ok) +} + +func TestThrowUnauthenticatedf(t *testing.T) { + err := caos_errs.ThrowUnauthenticatedf(nil, "id", "msg") + _, ok := err.(*caos_errs.UnauthenticatedError) + assert.True(t, ok) +} + +func TestIsUnauthenticated(t *testing.T) { + err := caos_errs.ThrowUnauthenticated(nil, "id", "msg") + ok := caos_errs.IsUnauthenticated(err) + assert.True(t, ok) + + err = errors.New("I am found!") + ok = caos_errs.IsUnauthenticated(err) + assert.False(t, ok) +} diff --git a/internal/errors/unavailable.go b/internal/errors/unavailable.go new file mode 100644 index 0000000000..e7e593a4c2 --- /dev/null +++ b/internal/errors/unavailable.go @@ -0,0 +1,34 @@ +package errors + +import ( + "fmt" +) + +var ( + _ Unavailable = (*UnavailableError)(nil) + _ Error = (*UnavailableError)(nil) +) + +type Unavailable interface { + error + IsUnavailable() +} + +type UnavailableError struct { + *CaosError +} + +func ThrowUnavailable(parent error, id, message string) error { + return &UnavailableError{createCaosError(parent, id, message)} +} + +func ThrowUnavailablef(parent error, id, format string, a ...interface{}) error { + return ThrowUnavailable(parent, id, fmt.Sprintf(format, a...)) +} + +func (err *UnavailableError) IsUnavailable() {} + +func IsUnavailable(err error) bool { + _, ok := err.(Unavailable) + return ok +} diff --git a/internal/errors/unavailable_test.go b/internal/errors/unavailable_test.go new file mode 100644 index 0000000000..818e6b66d0 --- /dev/null +++ b/internal/errors/unavailable_test.go @@ -0,0 +1,33 @@ +package errors_test + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/assert" + + caos_errs "github.com/caos/utils/errors" +) + +func TestUnavailableError(t *testing.T) { + var err interface{} + err = new(caos_errs.UnavailableError) + _, ok := err.(caos_errs.Unavailable) + assert.True(t, ok) +} + +func TestThrowUnavailablef(t *testing.T) { + err := caos_errs.ThrowUnavailablef(nil, "id", "msg") + _, ok := err.(*caos_errs.UnavailableError) + assert.True(t, ok) +} + +func TestIsUnavailable(t *testing.T) { + err := caos_errs.ThrowUnavailable(nil, "id", "msg") + ok := caos_errs.IsUnavailable(err) + assert.True(t, ok) + + err = errors.New("I am found!") + ok = caos_errs.IsUnavailable(err) + assert.False(t, ok) +} diff --git a/internal/errors/unimplemented.go b/internal/errors/unimplemented.go new file mode 100644 index 0000000000..1eea555b2a --- /dev/null +++ b/internal/errors/unimplemented.go @@ -0,0 +1,34 @@ +package errors + +import ( + "fmt" +) + +var ( + _ Unimplemented = (*UnimplementedError)(nil) + _ Error = (*UnimplementedError)(nil) +) + +type Unimplemented interface { + error + IsUnimplemented() +} + +type UnimplementedError struct { + *CaosError +} + +func ThrowUnimplemented(parent error, id, message string) error { + return &UnimplementedError{createCaosError(parent, id, message)} +} + +func ThrowUnimplementedf(parent error, id, format string, a ...interface{}) error { + return ThrowUnimplemented(parent, id, fmt.Sprintf(format, a...)) +} + +func (err *UnimplementedError) IsUnimplemented() {} + +func IsUnimplemented(err error) bool { + _, ok := err.(Unimplemented) + return ok +} diff --git a/internal/errors/unimplemented_test.go b/internal/errors/unimplemented_test.go new file mode 100644 index 0000000000..c146e90865 --- /dev/null +++ b/internal/errors/unimplemented_test.go @@ -0,0 +1,33 @@ +package errors_test + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/assert" + + caos_errs "github.com/caos/utils/errors" +) + +func TestUnimplementedError(t *testing.T) { + var unimplementedError interface{} + unimplementedError = new(caos_errs.UnimplementedError) + _, ok := unimplementedError.(caos_errs.Unimplemented) + assert.True(t, ok) +} + +func TestThrowUnimplementedf(t *testing.T) { + err := caos_errs.ThrowUnimplementedf(nil, "id", "msg") + _, ok := err.(*caos_errs.UnimplementedError) + assert.True(t, ok) +} + +func TestIsUnimplemented(t *testing.T) { + err := caos_errs.ThrowUnimplemented(nil, "id", "msg") + ok := caos_errs.IsUnimplemented(err) + assert.True(t, ok) + + err = errors.New("I am found!") + ok = caos_errs.IsUnimplemented(err) + assert.False(t, ok) +} diff --git a/internal/errors/unknown.go b/internal/errors/unknown.go new file mode 100644 index 0000000000..27d254adc4 --- /dev/null +++ b/internal/errors/unknown.go @@ -0,0 +1,34 @@ +package errors + +import ( + "fmt" +) + +var ( + _ Unknown = (*UnknownError)(nil) + _ Error = (*UnknownError)(nil) +) + +type Unknown interface { + error + IsUnknown() +} + +type UnknownError struct { + *CaosError +} + +func ThrowUnknown(parent error, id, message string) error { + return &UnknownError{createCaosError(parent, id, message)} +} + +func ThrowUnknownf(parent error, id, format string, a ...interface{}) error { + return ThrowUnknown(parent, id, fmt.Sprintf(format, a...)) +} + +func (err *UnknownError) IsUnknown() {} + +func IsUnknown(err error) bool { + _, ok := err.(Unknown) + return ok +} diff --git a/internal/errors/unknown_test.go b/internal/errors/unknown_test.go new file mode 100644 index 0000000000..9ec5e64073 --- /dev/null +++ b/internal/errors/unknown_test.go @@ -0,0 +1,33 @@ +package errors_test + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/assert" + + caos_errs "github.com/caos/utils/errors" +) + +func TestUnknownError(t *testing.T) { + var err interface{} + err = new(caos_errs.UnknownError) + _, ok := err.(caos_errs.Unknown) + assert.True(t, ok) +} + +func TestThrowUnknownf(t *testing.T) { + err := caos_errs.ThrowUnknownf(nil, "id", "msg") + _, ok := err.(*caos_errs.UnknownError) + assert.True(t, ok) +} + +func TestIsUnknown(t *testing.T) { + err := caos_errs.ThrowUnknown(nil, "id", "msg") + ok := caos_errs.IsUnknown(err) + assert.True(t, ok) + + err = errors.New("I am found!") + ok = caos_errs.IsUnknown(err) + assert.False(t, ok) +} From d3cb575e1d2215c174685283fffc28f20d53acfd Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Wed, 18 Mar 2020 15:45:55 +0100 Subject: [PATCH 05/39] added config pkg --- internal/config/config.go | 94 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 internal/config/config.go diff --git a/internal/config/config.go b/internal/config/config.go new file mode 100644 index 0000000000..c4b24a112e --- /dev/null +++ b/internal/config/config.go @@ -0,0 +1,94 @@ +package config + +import ( + "encoding/json" + "io/ioutil" + "os" + "path/filepath" + + "github.com/BurntSushi/toml" + "github.com/caos/logging" + "github.com/ghodss/yaml" + + "github.com/caos/zitadel/internal/errors" +) + +type Reader interface { + Unmarshal(data []byte, o interface{}) error +} + +type ValidatableConfiguration interface { + Validate() error +} + +type ReaderFunc func(data []byte, o interface{}) error + +func (c ReaderFunc) Unmarshal(data []byte, o interface{}) error { + return c(data, o) +} + +var ( + JSONReader = ReaderFunc(json.Unmarshal) + TOMLReader = ReaderFunc(toml.Unmarshal) + YAMLReader = ReaderFunc(func(y []byte, o interface{}) error { + return yaml.Unmarshal(y, o) + }) +) + +// Read deserializes each config file to the target obj +// using a Reader (depending on file extension) +// env vars are replaced in the config file as well as the file path +func Read(obj interface{}, configFiles ...string) error { + for _, cf := range configFiles { + configReader, err := configReaderForFile(cf) + if err != nil { + return err + } + if err := readConfigFile(configReader, cf, obj); err != nil { + return err + } + } + + if validatable, ok := obj.(ValidatableConfiguration); ok { + if err := validatable.Validate(); err != nil { + return err + } + } + + return nil +} + +func readConfigFile(configReader Reader, configFile string, obj interface{}) error { + configFile = os.ExpandEnv(configFile) + + if _, err := os.Stat(configFile); err != nil { + logging.LogWithFields("CONFI-Hs93M", "file", configFile).WithError(err).Warn("config file does not exist") + return nil + } + + configStr, err := ioutil.ReadFile(configFile) + if err != nil { + return errors.ThrowInternalf(err, "CONFI-nJk2a", "failed to read config file %s", configFile) + } + + configStr = []byte(os.ExpandEnv(string(configStr))) + + if err := configReader.Unmarshal(configStr, obj); err != nil { + return errors.ThrowInternalf(err, "CONFI-2Mc3c", "error parse config file %s", configFile) + } + + return nil +} + +func configReaderForFile(configFile string) (Reader, error) { + ext := filepath.Ext(configFile) + switch ext { + case ".yaml", ".yml": + return YAMLReader, nil + case ".json": + return JSONReader, nil + case ".toml": + return TOMLReader, nil + } + return nil, errors.ThrowUnimplementedf(nil, "file extension (%s) not supported", ext) +} From af8905036b54f874a4a3f7ae3a58b65c3e475950 Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Wed, 18 Mar 2020 15:46:41 +0100 Subject: [PATCH 06/39] added main cmd structure --- cmd/zitadel/main.go | 55 +++++++ go.mod | 9 ++ go.sum | 289 +++++++++++++++++++++++++++++++++++ pkg/admin/admin.go | 14 ++ pkg/auth/auth.go | 14 ++ pkg/eventstore/eventstore.go | 14 ++ pkg/management/management.go | 14 ++ 7 files changed, 409 insertions(+) create mode 100644 cmd/zitadel/main.go create mode 100644 go.sum create mode 100644 pkg/admin/admin.go create mode 100644 pkg/auth/auth.go create mode 100644 pkg/eventstore/eventstore.go create mode 100644 pkg/management/management.go diff --git a/cmd/zitadel/main.go b/cmd/zitadel/main.go new file mode 100644 index 0000000000..24f3f57abd --- /dev/null +++ b/cmd/zitadel/main.go @@ -0,0 +1,55 @@ +package main + +import ( + "context" + "flag" + + "github.com/caos/logging" + + "github.com/caos/zitadel/internal/config" + "github.com/caos/zitadel/pkg/admin" + "github.com/caos/zitadel/pkg/auth" + "github.com/caos/zitadel/pkg/eventstore" + "github.com/caos/zitadel/pkg/management" +) + +type Config struct { + Eventstore eventstore.Config + Management management.Config + Auth auth.Config + Admin admin.Config +} + +func main() { + configPath := flag.String("config-file", "/zitadel/config/startup.yaml", "path to the config file") + eventstoreEnabled := flag.Bool("eventstore", true, "enable eventstore") + managementEnabled := flag.Bool("management", true, "enable management api") + authEnabled := flag.Bool("auth", true, "enable auth api") + adminEnabled := flag.Bool("admin", true, "enable admin api") + + flag.Parse() + + conf := new(Config) + err := config.Read(conf, *configPath) + logging.Log("MAIN-FaF2r").OnError(err).Fatal("cannot read config") + + ctx := context.Background() + if *eventstoreEnabled { + err = eventstore.Start(ctx, conf.Eventstore) + logging.Log("MAIN-sj2Sd").OnError(err).Fatal("error starting eventstore") + } + if *managementEnabled { + err = management.Start(ctx, conf.Management) + logging.Log("MAIN-39Nv5").OnError(err).Fatal("error starting management api") + } + if *authEnabled { + err = auth.Start(ctx, conf.Auth) + logging.Log("MAIN-x0nD2").OnError(err).Fatal("error starting auth api") + } + if *adminEnabled { + err = admin.Start(ctx, conf.Admin) + logging.Log("MAIN-0na71").OnError(err).Fatal("error starting admin api") + } + <-ctx.Done() + logging.Log("MAIN-s8d2h").Info("stopping zitadel") +} diff --git a/go.mod b/go.mod index 688cb8fc60..b2256cbd49 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,12 @@ module github.com/caos/zitadel go 1.14 + +require ( + github.com/BurntSushi/toml v0.3.1 + github.com/caos/logging v0.0.0-20191210002624-b3260f690a6a + github.com/caos/utils v0.0.0-20200305060859-ac2fa70f313e // indirect + github.com/ghodss/yaml v1.0.0 + golang.org/x/sys v0.0.0-20200317113312-5766fd39f98d // indirect + gopkg.in/yaml.v2 v2.2.8 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000000..d0bf2fad7f --- /dev/null +++ b/go.sum @@ -0,0 +1,289 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +contrib.go.opencensus.io/exporter/stackdriver v0.13.0/go.mod h1:z2tyTZtPmQ2HvWH4cOmVDgtY+1lomfKdbLnkJvZdc8c= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/VictoriaMetrics/fastcache v1.5.7/go.mod h1:ptDBkNMQI4RtmVo8VS/XwRY6RoTu1dAWCbrk+6WsEM8= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q= +github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.29.16/go.mod h1:1KvfttTE3SPKMpo8g2c6jL3ZKfXtFvKscTgahTma5Xg= +github.com/caos/logging v0.0.0-20191210002624-b3260f690a6a h1:HOU/3xL/afsZ+2aCstfJlrzRkwYMTFR1TIEgps5ny8s= +github.com/caos/logging v0.0.0-20191210002624-b3260f690a6a/go.mod h1:9LKiDE2ChuGv6CHYif/kiugrfEXu9AwDiFWSreX7Wp0= +github.com/caos/utils v0.0.0-20200305060859-ac2fa70f313e h1:QSbTeoLPW7c1rWNJA2GOKunDJnRAfyg8+cb73qMYESM= +github.com/caos/utils v0.0.0-20200305060859-ac2fa70f313e/go.mod h1:CLEkNe7rs12GkdBWZxadA/mFiKeF6HzuA1BOKq+fX+Y= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/grpc-ecosystem/go-grpc-middleware v1.2.0/go.mod h1:mJzapYve32yjrKlk9GbyCZHuPgZsrbyIbyKhSzOpg6s= +github.com/grpc-ecosystem/grpc-gateway v1.13.0/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191206220618-eeba5f6aabab h1:FvshnhkKW+LO3HWHodML8kuVX8rnJTxKm9dFPuI68UM= +golang.org/x/sys v0.0.0-20191206220618-eeba5f6aabab/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200317113312-5766fd39f98d h1:62ap6LNOjDU6uGmKXHJbSfciMoV+FeI1sRXx/pLDL44= +golang.org/x/sys v0.0.0-20200317113312-5766fd39f98d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191010075000-0337d82405ff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.10.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200303153909-beee998c1893/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo= +gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/pkg/admin/admin.go b/pkg/admin/admin.go new file mode 100644 index 0000000000..fbbcbf4ed6 --- /dev/null +++ b/pkg/admin/admin.go @@ -0,0 +1,14 @@ +package admin + +import ( + "context" + + "github.com/caos/zitadel/internal/errors" +) + +type Config struct { +} + +func Start(ctx context.Context, config Config) error { + return errors.ThrowUnimplemented(nil, "", "") //TODO: implement +} diff --git a/pkg/auth/auth.go b/pkg/auth/auth.go new file mode 100644 index 0000000000..27ab548fa9 --- /dev/null +++ b/pkg/auth/auth.go @@ -0,0 +1,14 @@ +package auth + +import ( + "context" + + "github.com/caos/zitadel/internal/errors" +) + +type Config struct { +} + +func Start(ctx context.Context, config Config) error { + return errors.ThrowUnimplemented(nil, "", "") //TODO: implement +} diff --git a/pkg/eventstore/eventstore.go b/pkg/eventstore/eventstore.go new file mode 100644 index 0000000000..ef9d8ea6f5 --- /dev/null +++ b/pkg/eventstore/eventstore.go @@ -0,0 +1,14 @@ +package eventstore + +import ( + "context" + + "github.com/caos/zitadel/internal/errors" +) + +type Config struct { +} + +func Start(ctx context.Context, config Config) error { + return errors.ThrowUnimplemented(nil, "", "") //TODO: implement +} diff --git a/pkg/management/management.go b/pkg/management/management.go new file mode 100644 index 0000000000..8549042372 --- /dev/null +++ b/pkg/management/management.go @@ -0,0 +1,14 @@ +package management + +import ( + "context" + + "github.com/caos/zitadel/internal/errors" +) + +type Config struct { +} + +func Start(ctx context.Context, config Config) error { + return errors.ThrowUnimplemented(nil, "", "") //TODO: implement +} From 7ef62528d112c2be960c753c8330b98a2b45ff9c Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Thu, 19 Mar 2020 08:32:47 +0100 Subject: [PATCH 07/39] return error on file not found and added log ids and messages --- internal/config/config.go | 4 +--- pkg/admin/admin.go | 2 +- pkg/auth/auth.go | 2 +- pkg/eventstore/eventstore.go | 2 +- pkg/management/management.go | 2 +- 5 files changed, 5 insertions(+), 7 deletions(-) diff --git a/internal/config/config.go b/internal/config/config.go index c4b24a112e..5c524e1525 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -7,7 +7,6 @@ import ( "path/filepath" "github.com/BurntSushi/toml" - "github.com/caos/logging" "github.com/ghodss/yaml" "github.com/caos/zitadel/internal/errors" @@ -62,8 +61,7 @@ func readConfigFile(configReader Reader, configFile string, obj interface{}) err configFile = os.ExpandEnv(configFile) if _, err := os.Stat(configFile); err != nil { - logging.LogWithFields("CONFI-Hs93M", "file", configFile).WithError(err).Warn("config file does not exist") - return nil + return errors.ThrowNotFoundf(err, "CONFI-Hs93M", "config file %s does not exist", configFile) } configStr, err := ioutil.ReadFile(configFile) diff --git a/pkg/admin/admin.go b/pkg/admin/admin.go index fbbcbf4ed6..681fd53646 100644 --- a/pkg/admin/admin.go +++ b/pkg/admin/admin.go @@ -10,5 +10,5 @@ type Config struct { } func Start(ctx context.Context, config Config) error { - return errors.ThrowUnimplemented(nil, "", "") //TODO: implement + return errors.ThrowUnimplemented(nil, "ADMIN-n8vw5", "not implemented yet") //TODO: implement } diff --git a/pkg/auth/auth.go b/pkg/auth/auth.go index 27ab548fa9..0ac10202a3 100644 --- a/pkg/auth/auth.go +++ b/pkg/auth/auth.go @@ -10,5 +10,5 @@ type Config struct { } func Start(ctx context.Context, config Config) error { - return errors.ThrowUnimplemented(nil, "", "") //TODO: implement + return errors.ThrowUnimplemented(nil, "AUTH-l7Hdx", "not implemented yet") //TODO: implement } diff --git a/pkg/eventstore/eventstore.go b/pkg/eventstore/eventstore.go index ef9d8ea6f5..d07f825e44 100644 --- a/pkg/eventstore/eventstore.go +++ b/pkg/eventstore/eventstore.go @@ -10,5 +10,5 @@ type Config struct { } func Start(ctx context.Context, config Config) error { - return errors.ThrowUnimplemented(nil, "", "") //TODO: implement + return errors.ThrowUnimplemented(nil, "EVENT-1hfiu", "not implemented yet") //TODO: implement } diff --git a/pkg/management/management.go b/pkg/management/management.go index 8549042372..23bf517569 100644 --- a/pkg/management/management.go +++ b/pkg/management/management.go @@ -10,5 +10,5 @@ type Config struct { } func Start(ctx context.Context, config Config) error { - return errors.ThrowUnimplemented(nil, "", "") //TODO: implement + return errors.ThrowUnimplemented(nil, "MANAG-h3k3x", "not implemented yet") //TODO: implement } From 021ee07350f3bb929173a6297ef2c7f7441398a2 Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Mon, 23 Mar 2020 06:34:08 +0100 Subject: [PATCH 08/39] fix: imports in error pkg tests --- internal/errors/already_exists_test.go | 2 +- internal/errors/caos_error_test.go | 2 +- internal/errors/deadline_exceeded_test.go | 2 +- internal/errors/error_test.go | 2 +- internal/errors/generate/error_test.go.tmpl | 2 +- internal/errors/internal_test.go | 2 +- internal/errors/invalid_argument_test.go | 2 +- internal/errors/not_found_test.go | 2 +- internal/errors/permission_denied_test.go | 2 +- internal/errors/precondition_failed_test.go | 2 +- internal/errors/unauthenticated_test.go | 2 +- internal/errors/unavailable_test.go | 2 +- internal/errors/unimplemented_test.go | 2 +- internal/errors/unknown_test.go | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/internal/errors/already_exists_test.go b/internal/errors/already_exists_test.go index b239e777ba..9cac2badf2 100644 --- a/internal/errors/already_exists_test.go +++ b/internal/errors/already_exists_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/assert" - caos_errs "github.com/caos/utils/errors" + caos_errs "github.com/caos/zitadel/internal/errors" ) func TestAlreadyExistsError(t *testing.T) { diff --git a/internal/errors/caos_error_test.go b/internal/errors/caos_error_test.go index ce332ca361..7b93fd1963 100644 --- a/internal/errors/caos_error_test.go +++ b/internal/errors/caos_error_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/assert" - caos_errs "github.com/caos/utils/errors" + caos_errs "github.com/caos/zitadel/internal/errors" ) func TestErrorMethod(t *testing.T) { diff --git a/internal/errors/deadline_exceeded_test.go b/internal/errors/deadline_exceeded_test.go index 0758d6041e..30b9822a70 100644 --- a/internal/errors/deadline_exceeded_test.go +++ b/internal/errors/deadline_exceeded_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/assert" - caos_errs "github.com/caos/utils/errors" + caos_errs "github.com/caos/zitadel/internal/errors" ) func TestDeadlineExceededError(t *testing.T) { diff --git a/internal/errors/error_test.go b/internal/errors/error_test.go index da822d45ed..13ddd96fda 100644 --- a/internal/errors/error_test.go +++ b/internal/errors/error_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/assert" - caos_errors "github.com/caos/utils/errors" + caos_errors "github.com/caos/zitadel/internal/errors" ) func TestContains(t *testing.T) { diff --git a/internal/errors/generate/error_test.go.tmpl b/internal/errors/generate/error_test.go.tmpl index 6888001250..3b83a3a5ac 100644 --- a/internal/errors/generate/error_test.go.tmpl +++ b/internal/errors/generate/error_test.go.tmpl @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/assert" - caos_errs "github.com/caos/utils/errors" + caos_errs "github.com/caos/zitadel/internal/errors" ) func Test{{.ErrorName}}Error(t *testing.T) { diff --git a/internal/errors/internal_test.go b/internal/errors/internal_test.go index b6ceb6e43f..1c703a4d24 100644 --- a/internal/errors/internal_test.go +++ b/internal/errors/internal_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/assert" - caos_errs "github.com/caos/utils/errors" + caos_errs "github.com/caos/zitadel/internal/errors" ) func TestInternalError(t *testing.T) { diff --git a/internal/errors/invalid_argument_test.go b/internal/errors/invalid_argument_test.go index ca635eaaf4..e3a5797def 100644 --- a/internal/errors/invalid_argument_test.go +++ b/internal/errors/invalid_argument_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/assert" - caos_errs "github.com/caos/utils/errors" + caos_errs "github.com/caos/zitadel/internal/errors" ) func TestInvalidArgumentError(t *testing.T) { diff --git a/internal/errors/not_found_test.go b/internal/errors/not_found_test.go index 8c3b5e383a..00177112c8 100644 --- a/internal/errors/not_found_test.go +++ b/internal/errors/not_found_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/assert" - caos_errs "github.com/caos/utils/errors" + caos_errs "github.com/caos/zitadel/internal/errors" ) func TestNotFoundError(t *testing.T) { diff --git a/internal/errors/permission_denied_test.go b/internal/errors/permission_denied_test.go index e7fbf0f96c..05de1d15e7 100644 --- a/internal/errors/permission_denied_test.go +++ b/internal/errors/permission_denied_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/assert" - caos_errs "github.com/caos/utils/errors" + caos_errs "github.com/caos/zitadel/internal/errors" ) func TestPermissionDeniedError(t *testing.T) { diff --git a/internal/errors/precondition_failed_test.go b/internal/errors/precondition_failed_test.go index 7fc3e50dd9..df70d9ec90 100644 --- a/internal/errors/precondition_failed_test.go +++ b/internal/errors/precondition_failed_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/assert" - caos_errs "github.com/caos/utils/errors" + caos_errs "github.com/caos/zitadel/internal/errors" ) func TestPreconditionFailedError(t *testing.T) { diff --git a/internal/errors/unauthenticated_test.go b/internal/errors/unauthenticated_test.go index b64fd5f87b..56e469fd47 100644 --- a/internal/errors/unauthenticated_test.go +++ b/internal/errors/unauthenticated_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/assert" - caos_errs "github.com/caos/utils/errors" + caos_errs "github.com/caos/zitadel/internal/errors" ) func TestUnauthenticatedError(t *testing.T) { diff --git a/internal/errors/unavailable_test.go b/internal/errors/unavailable_test.go index 818e6b66d0..11f81af14f 100644 --- a/internal/errors/unavailable_test.go +++ b/internal/errors/unavailable_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/assert" - caos_errs "github.com/caos/utils/errors" + caos_errs "github.com/caos/zitadel/internal/errors" ) func TestUnavailableError(t *testing.T) { diff --git a/internal/errors/unimplemented_test.go b/internal/errors/unimplemented_test.go index c146e90865..f4c3178b02 100644 --- a/internal/errors/unimplemented_test.go +++ b/internal/errors/unimplemented_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/assert" - caos_errs "github.com/caos/utils/errors" + caos_errs "github.com/caos/zitadel/internal/errors" ) func TestUnimplementedError(t *testing.T) { diff --git a/internal/errors/unknown_test.go b/internal/errors/unknown_test.go index 9ec5e64073..4311289b40 100644 --- a/internal/errors/unknown_test.go +++ b/internal/errors/unknown_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/assert" - caos_errs "github.com/caos/utils/errors" + caos_errs "github.com/caos/zitadel/internal/errors" ) func TestUnknownError(t *testing.T) { From c89397e1b4632a4ca33ee97253f83f9c9d201477 Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Mon, 23 Mar 2020 07:01:59 +0100 Subject: [PATCH 09/39] feat: add some api packages --- go.mod | 18 +- go.sum | 222 ++---------- internal/api/auth/authorization.go | 108 ++++++ internal/api/auth/authorization_test.go | 280 +++++++++++++++ internal/api/auth/config.go | 26 ++ internal/api/auth/context.go | 70 ++++ internal/api/auth/permissions.go | 61 ++++ internal/api/auth/permissions_test.go | 431 ++++++++++++++++++++++++ internal/api/auth/token.go | 20 ++ internal/api/auth/token_test.go | 63 ++++ internal/api/grpc/auth_interceptor.go | 34 ++ internal/api/grpc/caos_errors.go | 46 +++ internal/api/grpc/error_interceptor.go | 14 + internal/api/grpc/header.go | 21 ++ internal/api/grpc/probes.go | 53 +++ internal/api/http/cookie.go | 125 +++++++ internal/api/http/parser.go | 28 ++ internal/proto/struct.go | 52 +++ internal/proto/struct_test.go | 53 +++ 19 files changed, 1535 insertions(+), 190 deletions(-) create mode 100644 internal/api/auth/authorization.go create mode 100644 internal/api/auth/authorization_test.go create mode 100644 internal/api/auth/config.go create mode 100644 internal/api/auth/context.go create mode 100644 internal/api/auth/permissions.go create mode 100644 internal/api/auth/permissions_test.go create mode 100644 internal/api/auth/token.go create mode 100644 internal/api/auth/token_test.go create mode 100644 internal/api/grpc/auth_interceptor.go create mode 100644 internal/api/grpc/caos_errors.go create mode 100644 internal/api/grpc/error_interceptor.go create mode 100644 internal/api/grpc/header.go create mode 100644 internal/api/grpc/probes.go create mode 100644 internal/api/http/cookie.go create mode 100644 internal/api/http/parser.go create mode 100644 internal/proto/struct.go create mode 100644 internal/proto/struct_test.go diff --git a/go.mod b/go.mod index b2256cbd49..d6ffe46cdf 100644 --- a/go.mod +++ b/go.mod @@ -5,8 +5,22 @@ go 1.14 require ( github.com/BurntSushi/toml v0.3.1 github.com/caos/logging v0.0.0-20191210002624-b3260f690a6a - github.com/caos/utils v0.0.0-20200305060859-ac2fa70f313e // indirect github.com/ghodss/yaml v1.0.0 - golang.org/x/sys v0.0.0-20200317113312-5766fd39f98d // indirect + github.com/golang/mock v1.4.3 + github.com/golang/protobuf v1.3.5 + github.com/google/go-cmp v0.4.0 // indirect + github.com/gorilla/schema v1.1.0 + github.com/gorilla/securecookie v1.1.1 + github.com/grpc-ecosystem/go-grpc-middleware v1.2.0 + github.com/kr/pretty v0.1.0 // indirect + github.com/stretchr/testify v1.5.1 + golang.org/x/crypto v0.0.0-20200320181102-891825fb96df + golang.org/x/net v0.0.0-20200320220750-118fecf932d8 // indirect + golang.org/x/sys v0.0.0-20200321134203-328b4cd54aae // indirect + golang.org/x/text v0.3.2 // indirect + google.golang.org/genproto v0.0.0-20200319113533-08878b785e9c // indirect + google.golang.org/grpc v1.28.0 + gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect gopkg.in/yaml.v2 v2.2.8 // indirect + rsc.io/sampler v1.99.99 // indirect ) diff --git a/go.sum b/go.sum index d0bf2fad7f..f39134d478 100644 --- a/go.sum +++ b/go.sum @@ -1,289 +1,135 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -contrib.go.opencensus.io/exporter/stackdriver v0.13.0/go.mod h1:z2tyTZtPmQ2HvWH4cOmVDgtY+1lomfKdbLnkJvZdc8c= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/VictoriaMetrics/fastcache v1.5.7/go.mod h1:ptDBkNMQI4RtmVo8VS/XwRY6RoTu1dAWCbrk+6WsEM8= -github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= -github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= -github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q= -github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.29.16/go.mod h1:1KvfttTE3SPKMpo8g2c6jL3ZKfXtFvKscTgahTma5Xg= github.com/caos/logging v0.0.0-20191210002624-b3260f690a6a h1:HOU/3xL/afsZ+2aCstfJlrzRkwYMTFR1TIEgps5ny8s= github.com/caos/logging v0.0.0-20191210002624-b3260f690a6a/go.mod h1:9LKiDE2ChuGv6CHYif/kiugrfEXu9AwDiFWSreX7Wp0= -github.com/caos/utils v0.0.0-20200305060859-ac2fa70f313e h1:QSbTeoLPW7c1rWNJA2GOKunDJnRAfyg8+cb73qMYESM= -github.com/caos/utils v0.0.0-20200305060859-ac2fa70f313e/go.mod h1:CLEkNe7rs12GkdBWZxadA/mFiKeF6HzuA1BOKq+fX+Y= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3 h1:GV+pQPG/EUUbkh47niozDcADz6go/dUwhVzdUQHIVRw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/gorilla/schema v1.1.0 h1:CamqUDOFUBqzrvxuz2vEwo8+SUdwsluFh7IlzJh30LY= +github.com/gorilla/schema v1.1.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU= +github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= +github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= +github.com/grpc-ecosystem/go-grpc-middleware v1.2.0 h1:0IKlLyQ3Hs9nDaiK5cSHAGmcQEIC8l2Ts1u6x5Dfrqg= github.com/grpc-ecosystem/go-grpc-middleware v1.2.0/go.mod h1:mJzapYve32yjrKlk9GbyCZHuPgZsrbyIbyKhSzOpg6s= -github.com/grpc-ecosystem/grpc-gateway v1.13.0/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200320181102-891825fb96df h1:lDWgvUvNnaTnNBc/dwOty86cFeKoKWbwy2wQj0gIxbU= +golang.org/x/crypto v0.0.0-20200320181102-891825fb96df/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200320220750-118fecf932d8 h1:1+zQlQqEEhUeStBTi653GZAnAuivZq/2hz+Iz+OP7rg= +golang.org/x/net v0.0.0-20200320220750-118fecf932d8/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191206220618-eeba5f6aabab h1:FvshnhkKW+LO3HWHodML8kuVX8rnJTxKm9dFPuI68UM= golang.org/x/sys v0.0.0-20191206220618-eeba5f6aabab/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200317113312-5766fd39f98d h1:62ap6LNOjDU6uGmKXHJbSfciMoV+FeI1sRXx/pLDL44= -golang.org/x/sys v0.0.0-20200317113312-5766fd39f98d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200321134203-328b4cd54aae h1:3tcmuaB7wwSZtelmiv479UjUB+vviwABz7a133ZwOKQ= +golang.org/x/sys v0.0.0-20200321134203-328b4cd54aae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135 h1:5Beo0mZN8dRzgrMMkDp0jc8YXQKx9DiJ2k1dkvGsn5A= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191010075000-0337d82405ff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.10.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200303153909-beee998c1893/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200319113533-08878b785e9c h1:5aI3/f/3eCZps9xwoEnmgfDJDhMbnJpfqeGpjVNgVEI= +google.golang.org/genproto v0.0.0-20200319113533-08878b785e9c/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0 h1:bO/TA4OxCOummhSf10siHuG7vJOiwh7SpRpFZDkOgl4= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo= gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0 h1:9JKUTTIUgS6kzR9mK1YuGKv6Nl+DijDNIc0ghT58FaY= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +rsc.io/sampler v1.99.99 h1:7i08f/p5TBU5joCPW3GjWG1ZFCmr28ybGqlXtelhEK8= +rsc.io/sampler v1.99.99/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/internal/api/auth/authorization.go b/internal/api/auth/authorization.go new file mode 100644 index 0000000000..5f7f31ec41 --- /dev/null +++ b/internal/api/auth/authorization.go @@ -0,0 +1,108 @@ +package auth + +import ( + "context" + "fmt" + "reflect" + "strings" + + "github.com/caos/zitadel/internal/errors" +) + +const ( + authenticated = "authenticated" +) + +func CheckUserAuthorization(ctx context.Context, req interface{}, token, orgID string, verifier TokenVerifier, authConfig *Config, requiredAuthOption Option) (context.Context, error) { + ctx, err := VerifyTokenAndWriteCtxData(ctx, token, orgID, verifier) + if err != nil { + return nil, err + } + + if requiredAuthOption.Permission == authenticated { + return ctx, nil + } + + ctx, perms, err := getUserMethodPermissions(ctx, verifier, requiredAuthOption.Permission, authConfig) + if err != nil { + return nil, err + } + + err = checkUserPermissions(req, perms, requiredAuthOption) + if err != nil { + return nil, err + } + return ctx, nil +} + +func checkUserPermissions(req interface{}, userPerms []string, authOpt Option) error { + if len(userPerms) == 0 { + return errors.ThrowPermissionDenied(nil, "AUTH-5mWD2", "No matching permissions found") + } + + if authOpt.CheckParam == "" { + return nil + } + + if HasGlobalPermission(userPerms) { + return nil + } + + if hasContextPermission(req, authOpt.CheckParam, userPerms) { + return nil + } + + return errors.ThrowPermissionDenied(nil, "AUTH-3jknH", "No matching permissions found") +} + +func SplitPermission(perm string) (string, string) { + splittedPerm := strings.Split(perm, ":") + if len(splittedPerm) == 1 { + return splittedPerm[0], "" + } + return splittedPerm[0], splittedPerm[1] +} + +func hasContextPermission(req interface{}, fieldName string, permissions []string) bool { + for _, perm := range permissions { + _, ctxID := SplitPermission(perm) + if checkPermissionContext(req, fieldName, ctxID) { + return true + } + } + return false +} + +func checkPermissionContext(req interface{}, fieldName, roleContextID string) bool { + field := getFieldFromReq(req, fieldName) + return field != "" && field == roleContextID +} + +func getFieldFromReq(req interface{}, field string) string { + v := reflect.Indirect(reflect.ValueOf(req)).FieldByName(field) + if reflect.ValueOf(v).IsZero() { + return "" + } + return fmt.Sprintf("%v", v.Interface()) +} + +func HasGlobalPermission(perms []string) bool { + for _, perm := range perms { + _, ctxID := SplitPermission(perm) + if ctxID == "" { + return true + } + } + return false +} + +func GetPermissionCtxIDs(perms []string) []string { + ctxIDs := make([]string, 0) + for _, perm := range perms { + _, ctxID := SplitPermission(perm) + if ctxID != "" { + ctxIDs = append(ctxIDs, ctxID) + } + } + return ctxIDs +} diff --git a/internal/api/auth/authorization_test.go b/internal/api/auth/authorization_test.go new file mode 100644 index 0000000000..5282e10c92 --- /dev/null +++ b/internal/api/auth/authorization_test.go @@ -0,0 +1,280 @@ +package auth + +import ( + "testing" + + "github.com/caos/zitadel/internal/errors" +) + +type TestRequest struct { + Test string +} + +func Test_CheckUserPermissions(t *testing.T) { + type args struct { + req *TestRequest + perms []string + authOpt Option + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "no permissions", + args: args{ + req: &TestRequest{}, + perms: []string{}, + }, + wantErr: true, + }, + { + name: "has permission and no context requested", + args: args{ + req: &TestRequest{}, + perms: []string{"project.read"}, + authOpt: Option{CheckParam: ""}, + }, + wantErr: false, + }, + { + name: "context requested and has global permission", + args: args{ + req: &TestRequest{Test: "Test"}, + perms: []string{"project.read", "project.read:1"}, + authOpt: Option{CheckParam: "Test"}, + }, + wantErr: false, + }, + { + name: "context requested and has specific permission", + args: args{ + req: &TestRequest{Test: "Test"}, + perms: []string{"project.read:Test"}, + authOpt: Option{CheckParam: "Test"}, + }, + wantErr: false, + }, + { + name: "context requested and has no permission", + args: args{ + req: &TestRequest{Test: "Hodor"}, + perms: []string{"project.read:Test"}, + authOpt: Option{CheckParam: "Test"}, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := checkUserPermissions(tt.args.req, tt.args.perms, tt.args.authOpt) + if tt.wantErr && err == nil { + t.Errorf("got wrong result, should get err: actual: %v ", err) + } + + if !tt.wantErr && err != nil { + t.Errorf("shouldn't get err: %v ", err) + } + + if tt.wantErr && !errors.IsPermissionDenied(err) { + t.Errorf("got wrong err: %v ", err) + } + }) + } +} + +func Test_SplitPermission(t *testing.T) { + type args struct { + perm string + } + tests := []struct { + name string + args args + permName string + permCtxID string + }{ + { + name: "permission with context id", + args: args{ + perm: "project.read:ctxID", + }, + permName: "project.read", + permCtxID: "ctxID", + }, + { + name: "permission without context id", + args: args{ + perm: "project.read", + }, + permName: "project.read", + permCtxID: "", + }, + { + name: "permission to many parts", + args: args{ + perm: "project.read:1:0", + }, + permName: "project.read", + permCtxID: "1", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + name, id := SplitPermission(tt.args.perm) + if name != tt.permName { + t.Errorf("got wrong result on name, expecting: %v, actual: %v ", tt.permName, name) + } + if id != tt.permCtxID { + t.Errorf("got wrong result on id, expecting: %v, actual: %v ", tt.permCtxID, id) + } + }) + } +} + +func Test_HasContextPermission(t *testing.T) { + type args struct { + req *TestRequest + fieldname string + perms []string + } + tests := []struct { + name string + args args + result bool + }{ + { + name: "existing context permission", + args: args{ + req: &TestRequest{Test: "right"}, + fieldname: "Test", + perms: []string{"test:wrong", "test:right"}, + }, + result: true, + }, + { + name: "not existing context permission", + args: args{ + req: &TestRequest{Test: "test"}, + fieldname: "Test", + perms: []string{"test:wrong", "test:wrong2"}, + }, + result: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := hasContextPermission(tt.args.req, tt.args.fieldname, tt.args.perms) + if result != tt.result { + t.Errorf("got wrong result, expecting: %v, actual: %v ", tt.result, result) + } + }) + } +} + +func Test_GetFieldFromReq(t *testing.T) { + type args struct { + req *TestRequest + fieldname string + } + tests := []struct { + name string + args args + result string + }{ + { + name: "existing field", + args: args{ + req: &TestRequest{Test: "TestValue"}, + fieldname: "Test", + }, + result: "TestValue", + }, + { + name: "not existing field", + args: args{ + req: &TestRequest{Test: "TestValue"}, + fieldname: "Test2", + }, + result: "", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := getFieldFromReq(tt.args.req, tt.args.fieldname) + if result != tt.result { + t.Errorf("got wrong result, expecting: %v, actual: %v ", tt.result, result) + } + }) + } +} + +func Test_HasGlobalPermission(t *testing.T) { + + type args struct { + perms []string + } + tests := []struct { + name string + args args + result bool + }{ + { + name: "global perm existing", + args: args{ + perms: []string{"perm:1", "perm:2", "perm"}, + }, + result: true, + }, + { + name: "global perm not existing", + args: args{ + perms: []string{"perm:1", "perm:2", "perm:3"}, + }, + result: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := HasGlobalPermission(tt.args.perms) + if result != tt.result { + t.Errorf("got wrong result, expecting: %v, actual: %v ", tt.result, result) + } + }) + } +} + +func Test_GetPermissionCtxIDs(t *testing.T) { + + type args struct { + perms []string + } + tests := []struct { + name string + args args + result []string + }{ + { + name: "no specific permission", + args: args{ + perms: []string{"perm"}, + }, + result: []string{}, + }, + { + name: "ctx id", + args: args{ + perms: []string{"perm:1", "perm", "perm:3"}, + }, + result: []string{"1", "3"}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := GetPermissionCtxIDs(tt.args.perms) + if !EqualStringArray(result, tt.result) { + t.Errorf("got wrong result, expecting: %v, actual: %v ", tt.result, result) + } + }) + } +} diff --git a/internal/api/auth/config.go b/internal/api/auth/config.go new file mode 100644 index 0000000000..b678fe377e --- /dev/null +++ b/internal/api/auth/config.go @@ -0,0 +1,26 @@ +package auth + +type Config struct { + RolePermissionMappings []RoleMapping +} + +type RoleMapping struct { + Role string + Permissions []string +} + +type MethodMapping map[string]Option + +type Option struct { + Permission string + CheckParam string +} + +func (a *Config) getPermissionsFromRole(role string) []string { + for _, roleMap := range a.RolePermissionMappings { + if roleMap.Role == role { + return roleMap.Permissions + } + } + return nil +} diff --git a/internal/api/auth/context.go b/internal/api/auth/context.go new file mode 100644 index 0000000000..5638fa40d1 --- /dev/null +++ b/internal/api/auth/context.go @@ -0,0 +1,70 @@ +package auth + +import ( + "context" + "time" + + "github.com/caos/logging" +) + +const ( + HeaderOrgID = "x-caos-zitadel-orgid" +) + +type CtxKeyPermissions struct{} +type CtxKeyData struct{} + +type CtxData struct { + UserID string + OrgID string + ProjectID string + AgentID string +} + +func (ctxData CtxData) IsZero() bool { + return ctxData.UserID == "" || ctxData.OrgID == "" +} + +type Grants []*Grant + +type Grant struct { + OrgID string + Roles []string +} + +type TokenVerifier interface { + VerifyAccessToken(ctx context.Context, token string) (string, string, string, error) + ResolveGrants(ctx context.Context, sub, orgID string) ([]*Grant, error) + GetProjectIDByClientID(ctx context.Context, clientID string) (string, error) +} + +func VerifyTokenAndWriteCtxData(ctx context.Context, token, orgID string, t TokenVerifier) (_ context.Context, err error) { + userID, clientID, agentID, err := verifyAccessToken(ctx, token, t) + if err != nil { + return nil, err + } + + projectID, err := t.GetProjectIDByClientID(ctx, clientID) + logging.LogWithFields("AUTH-GfAoV", "clientID", clientID).OnError(err).Warn("could not read projectid by clientid") + + return context.WithValue(ctx, CtxKeyData{}, &CtxData{UserID: userID, OrgID: orgID, ProjectID: projectID, AgentID: agentID}), nil +} + +func GetCtxData(ctx context.Context) CtxData { + if data := ctx.Value(CtxKeyData{}); data != nil { + ctxData, ok := data.(*CtxData) + if ok { + return *ctxData + } + time.Now() + } + return CtxData{} +} + +func GetPermissionsFromCtx(ctx context.Context) []string { + if data := ctx.Value(CtxKeyPermissions{}); data != nil { + ctxPermission, _ := data.([]string) + return ctxPermission + } + return nil +} diff --git a/internal/api/auth/permissions.go b/internal/api/auth/permissions.go new file mode 100644 index 0000000000..d7ca516a9d --- /dev/null +++ b/internal/api/auth/permissions.go @@ -0,0 +1,61 @@ +package auth + +import ( + "context" + + "github.com/caos/zitadel/internal/errors" +) + +func getUserMethodPermissions(ctx context.Context, t TokenVerifier, requiredPerm string, authConfig *Config) (context.Context, []string, error) { + ctxData := GetCtxData(ctx) + if ctxData.IsZero() { + return nil, nil, errors.ThrowUnauthenticated(nil, "AUTH-rKLWEH", "context missing") + } + grants, err := t.ResolveGrants(ctx, ctxData.UserID, ctxData.OrgID) + if err != nil { + return nil, nil, err + } + permissions := mapGrantsToPermissions(requiredPerm, grants, authConfig) + return context.WithValue(ctx, CtxKeyPermissions{}, permissions), permissions, nil +} + +func mapGrantsToPermissions(requiredPerm string, grants []*Grant, authConfig *Config) []string { + resolvedPermissions := make([]string, 0) + for _, grant := range grants { + for _, role := range grant.Roles { + resolvedPermissions = mapRoleToPerm(requiredPerm, role, authConfig, resolvedPermissions) + } + } + return resolvedPermissions +} + +func mapRoleToPerm(requiredPerm, actualRole string, authConfig *Config, resolvedPermissions []string) []string { + roleName, roleContextID := SplitPermission(actualRole) + perms := authConfig.getPermissionsFromRole(roleName) + + for _, p := range perms { + if p == requiredPerm { + p = addRoleContextIDToPerm(p, roleContextID) + if !existsPerm(resolvedPermissions, p) { + resolvedPermissions = append(resolvedPermissions, p) + } + } + } + return resolvedPermissions +} + +func addRoleContextIDToPerm(perm, roleContextID string) string { + if roleContextID != "" { + perm = perm + ":" + roleContextID + } + return perm +} + +func existsPerm(existing []string, perm string) bool { + for _, e := range existing { + if e == perm { + return true + } + } + return false +} diff --git a/internal/api/auth/permissions_test.go b/internal/api/auth/permissions_test.go new file mode 100644 index 0000000000..6d0857d792 --- /dev/null +++ b/internal/api/auth/permissions_test.go @@ -0,0 +1,431 @@ +package auth + +import ( + "context" + "testing" + + caos_errs "github.com/caos/zitadel/internal/errors" +) + +func getTestCtx(userID, orgID string) context.Context { + return context.WithValue(context.Background(), CtxKeyData{}, &CtxData{UserID: userID, OrgID: orgID}) +} + +type testVerifier struct { + grants []*Grant +} + +func (v *testVerifier) VerifyAccessToken(ctx context.Context, token string) (string, string, string, error) { + return "", "", "", nil +} + +func (v *testVerifier) ResolveGrants(ctx context.Context, sub, orgID string) ([]*Grant, error) { + return v.grants, nil +} + +func (v *testVerifier) GetProjectIDByClientID(ctx context.Context, clientID string) (string, error) { + return "", nil +} + +func EqualStringArray(a, b []string) bool { + if len(a) != len(b) { + return false + } + for i, v := range a { + if v != b[i] { + return false + } + } + return true +} + +func Test_GetUserMethodPermissions(t *testing.T) { + type args struct { + ctx context.Context + verifier TokenVerifier + requiredPerm string + authConfig *Config + } + tests := []struct { + name string + args args + wantErr bool + errFunc func(err error) bool + result []string + }{ + { + name: "Empty Context", + args: args{ + ctx: getTestCtx("", ""), + verifier: &testVerifier{grants: []*Grant{&Grant{ + Roles: []string{"ORG_OWNER"}}}}, + requiredPerm: "project.read", + authConfig: &Config{ + RolePermissionMappings: []RoleMapping{ + RoleMapping{ + Role: "IAM_OWNER", + Permissions: []string{"project.read"}, + }, + RoleMapping{ + Role: "ORG_OWNER", + Permissions: []string{"org.read", "project.read"}, + }, + }, + }, + }, + wantErr: true, + errFunc: func(err error) bool { + return caos_errs.IsUnauthenticated(err) + }, + result: []string{"project.read"}, + }, + { + name: "No Grants", + args: args{ + ctx: getTestCtx("", ""), + verifier: &testVerifier{grants: []*Grant{}}, + requiredPerm: "project.read", + authConfig: &Config{ + RolePermissionMappings: []RoleMapping{ + RoleMapping{ + Role: "IAM_OWNER", + Permissions: []string{"project.read"}, + }, + RoleMapping{ + Role: "ORG_OWNER", + Permissions: []string{"org.read", "project.read"}, + }, + }, + }, + }, + result: make([]string, 0), + }, + { + name: "Get Permissions", + args: args{ + ctx: getTestCtx("userID", "orgID"), + verifier: &testVerifier{grants: []*Grant{&Grant{ + Roles: []string{"ORG_OWNER"}}}}, + requiredPerm: "project.read", + authConfig: &Config{ + RolePermissionMappings: []RoleMapping{ + RoleMapping{ + Role: "IAM_OWNER", + Permissions: []string{"project.read"}, + }, + RoleMapping{ + Role: "ORG_OWNER", + Permissions: []string{"org.read", "project.read"}, + }, + }, + }, + }, + result: []string{"project.read"}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + _, perms, err := getUserMethodPermissions(tt.args.ctx, tt.args.verifier, tt.args.requiredPerm, tt.args.authConfig) + + if tt.wantErr && err == nil { + t.Errorf("got wrong result, should get err: actual: %v ", err) + } + + if tt.wantErr && !tt.errFunc(err) { + t.Errorf("got wrong err: %v ", err) + } + + if !tt.wantErr && !EqualStringArray(perms, tt.result) { + t.Errorf("got wrong result, expecting: %v, actual: %v ", tt.result, perms) + } + }) + } +} + +func Test_MapGrantsToPermissions(t *testing.T) { + type args struct { + requiredPerm string + grants []*Grant + authConfig *Config + } + tests := []struct { + name string + args args + result []string + }{ + { + name: "One Role existing perm", + args: args{ + requiredPerm: "project.read", + grants: []*Grant{&Grant{ + Roles: []string{"ORG_OWNER"}}}, + authConfig: &Config{ + RolePermissionMappings: []RoleMapping{ + RoleMapping{ + Role: "IAM_OWNER", + Permissions: []string{"project.read"}, + }, + RoleMapping{ + Role: "ORG_OWNER", + Permissions: []string{"org.read", "project.read"}, + }, + }, + }, + }, + result: []string{"project.read"}, + }, + { + name: "One Role not existing perm", + args: args{ + requiredPerm: "project.write", + grants: []*Grant{&Grant{ + Roles: []string{"ORG_OWNER"}}}, + authConfig: &Config{ + RolePermissionMappings: []RoleMapping{ + RoleMapping{ + Role: "IAM_OWNER", + Permissions: []string{"project.read"}, + }, + RoleMapping{ + Role: "ORG_OWNER", + Permissions: []string{"org.read", "project.read"}, + }, + }, + }, + }, + result: []string{}, + }, + { + name: "Multiple Roles one existing", + args: args{ + requiredPerm: "project.read", + grants: []*Grant{&Grant{ + Roles: []string{"ORG_OWNER", "IAM_OWNER"}}}, + authConfig: &Config{ + RolePermissionMappings: []RoleMapping{ + RoleMapping{ + Role: "IAM_OWNER", + Permissions: []string{"project.read"}, + }, + RoleMapping{ + Role: "ORG_OWNER", + Permissions: []string{"org.read", "project.read"}, + }, + }, + }, + }, + result: []string{"project.read"}, + }, + { + name: "Multiple Roles, global and specific", + args: args{ + requiredPerm: "project.read", + grants: []*Grant{&Grant{ + Roles: []string{"ORG_OWNER", "PROJECT_OWNER:1"}}}, + authConfig: &Config{ + RolePermissionMappings: []RoleMapping{ + RoleMapping{ + Role: "PROJECT_OWNER", + Permissions: []string{"project.read"}, + }, + RoleMapping{ + Role: "ORG_OWNER", + Permissions: []string{"org.read", "project.read"}, + }, + }, + }, + }, + result: []string{"project.read", "project.read:1"}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := mapGrantsToPermissions(tt.args.requiredPerm, tt.args.grants, tt.args.authConfig) + if !EqualStringArray(result, tt.result) { + t.Errorf("got wrong result, expecting: %v, actual: %v ", tt.result, result) + } + }) + } +} + +func Test_MapRoleToPerm(t *testing.T) { + type args struct { + requiredPerm string + actualRole string + authConfig *Config + resolvedPermissions []string + } + tests := []struct { + name string + args args + result []string + }{ + { + name: "first perm without context id", + args: args{ + requiredPerm: "project.read", + actualRole: "ORG_OWNER", + authConfig: &Config{ + RolePermissionMappings: []RoleMapping{ + RoleMapping{ + Role: "IAM_OWNER", + Permissions: []string{"project.read"}, + }, + RoleMapping{ + Role: "ORG_OWNER", + Permissions: []string{"org.read", "project.read"}, + }, + }, + }, + resolvedPermissions: []string{}, + }, + result: []string{"project.read"}, + }, + { + name: "existing perm without context id", + args: args{ + requiredPerm: "project.read", + actualRole: "ORG_OWNER", + authConfig: &Config{ + RolePermissionMappings: []RoleMapping{ + RoleMapping{ + Role: "IAM_OWNER", + Permissions: []string{"project.read"}, + }, + RoleMapping{ + Role: "ORG_OWNER", + Permissions: []string{"org.read", "project.read"}, + }, + }, + }, + resolvedPermissions: []string{"project.read"}, + }, + result: []string{"project.read"}, + }, + { + name: "first perm with context id", + args: args{ + requiredPerm: "project.read", + actualRole: "PROJECT_OWNER:1", + authConfig: &Config{ + RolePermissionMappings: []RoleMapping{ + RoleMapping{ + Role: "PROJECT_OWNER", + Permissions: []string{"project.read"}, + }, + RoleMapping{ + Role: "ORG_OWNER", + Permissions: []string{"org.read", "project.read"}, + }, + }, + }, + resolvedPermissions: []string{}, + }, + result: []string{"project.read:1"}, + }, + { + name: "perm with context id, existing global", + args: args{ + requiredPerm: "project.read", + actualRole: "PROJECT_OWNER:1", + authConfig: &Config{ + RolePermissionMappings: []RoleMapping{ + RoleMapping{ + Role: "PROJECT_OWNER", + Permissions: []string{"project.read"}, + }, + RoleMapping{ + Role: "ORG_OWNER", + Permissions: []string{"org.read", "project.read"}, + }, + }, + }, + resolvedPermissions: []string{"project.read"}, + }, + result: []string{"project.read", "project.read:1"}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := mapRoleToPerm(tt.args.requiredPerm, tt.args.actualRole, tt.args.authConfig, tt.args.resolvedPermissions) + if !EqualStringArray(result, tt.result) { + t.Errorf("got wrong result, expecting: %v, actual: %v ", tt.result, result) + } + }) + } +} + +func Test_AddRoleContextIDToPerm(t *testing.T) { + type args struct { + perm string + ctxID string + } + tests := []struct { + name string + args args + result string + }{ + { + name: "with ctx id", + args: args{ + perm: "perm1", + ctxID: "2", + }, + result: "perm1:2", + }, + { + name: "with ctx id", + args: args{ + perm: "perm1", + ctxID: "", + }, + result: "perm1", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := addRoleContextIDToPerm(tt.args.perm, tt.args.ctxID) + if result != tt.result { + t.Errorf("got wrong result, expecting: %v, actual: %v ", tt.result, result) + } + }) + } +} + +func Test_ExistisPerm(t *testing.T) { + + type args struct { + existing []string + perm string + } + tests := []struct { + name string + args args + result bool + }{ + { + name: "not existing perm", + args: args{ + existing: []string{"perm1", "perm2", "perm3"}, + perm: "perm4", + }, + result: false, + }, + { + name: "existing perm", + args: args{ + existing: []string{"perm1", "perm2", "perm3"}, + perm: "perm2", + }, + result: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := existsPerm(tt.args.existing, tt.args.perm) + if result != tt.result { + t.Errorf("got wrong result, expecting: %v, actual: %v ", tt.result, result) + } + }) + } +} diff --git a/internal/api/auth/token.go b/internal/api/auth/token.go new file mode 100644 index 0000000000..7aab34eb9e --- /dev/null +++ b/internal/api/auth/token.go @@ -0,0 +1,20 @@ +package auth + +import ( + "context" + "strings" + + "github.com/caos/zitadel/internal/errors" +) + +const ( + BearerPrefix = "Bearer " +) + +func verifyAccessToken(ctx context.Context, token string, t TokenVerifier) (string, string, string, error) { + parts := strings.Split(token, BearerPrefix) + if len(parts) != 2 { + return "", "", "", errors.ThrowUnauthenticated(nil, "AUTH-7fs1e", "invalid auth header") + } + return t.VerifyAccessToken(ctx, parts[1]) +} diff --git a/internal/api/auth/token_test.go b/internal/api/auth/token_test.go new file mode 100644 index 0000000000..827817b3a4 --- /dev/null +++ b/internal/api/auth/token_test.go @@ -0,0 +1,63 @@ +package auth + +import ( + "context" + "testing" + + "github.com/caos/zitadel/internal/errors" +) + +func Test_VerifyAccessToken(t *testing.T) { + + type args struct { + ctx context.Context + token string + verifier *testVerifier + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "no auth header set", + args: args{ + ctx: context.Background(), + token: "", + }, + wantErr: true, + }, + { + name: "wrong auth header set", + args: args{ + ctx: context.Background(), + token: "Basic sds", + }, + wantErr: true, + }, + { + name: "auth header set", + args: args{ + ctx: context.Background(), + token: "Bearer AUTH", + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + _, _, _, err := verifyAccessToken(tt.args.ctx, tt.args.token, tt.args.verifier) + if tt.wantErr && err == nil { + t.Errorf("got wrong result, should get err: actual: %v ", err) + } + + if !tt.wantErr && err != nil { + t.Errorf("got wrong result, should not get err: actual: %v ", err) + } + + if tt.wantErr && !errors.IsUnauthenticated(err) { + t.Errorf("got wrong err: %v ", err) + } + }) + } +} diff --git a/internal/api/grpc/auth_interceptor.go b/internal/api/grpc/auth_interceptor.go new file mode 100644 index 0000000000..4e91d11714 --- /dev/null +++ b/internal/api/grpc/auth_interceptor.go @@ -0,0 +1,34 @@ +package grpc + +import ( + "context" + + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + "github.com/caos/zitadel/internal/api/auth" +) + +func AuthorizationInterceptor(verifier auth.TokenVerifier, authConfig *auth.Config, authMethods auth.MethodMapping) func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + authOpt, needsToken := authMethods[info.FullMethod] + if !needsToken { + return handler(ctx, req) + } + + authToken := GetAuthorizationHeader(ctx) + if authToken == "" { + return nil, status.Error(codes.Unauthenticated, "auth header missing") + } + + orgID := GetHeader(ctx, ZitadelOrgID) + + ctx, err := auth.CheckUserAuthorization(ctx, req, authToken, orgID, verifier, authConfig, authOpt) + if err != nil { + return nil, err + } + + return handler(ctx, req) + } +} diff --git a/internal/api/grpc/caos_errors.go b/internal/api/grpc/caos_errors.go new file mode 100644 index 0000000000..5ed7fa95da --- /dev/null +++ b/internal/api/grpc/caos_errors.go @@ -0,0 +1,46 @@ +package grpc + +import ( + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + caos_errs "github.com/caos/zitadel/internal/errors" +) + +func CaosToGRPCError(err error) error { + if err == nil { + return nil + } + code, msg, ok := extract(err) + if !ok { + return status.Convert(err).Err() + } + return status.Error(code, msg) +} + +func extract(err error) (c codes.Code, msg string, ok bool) { + switch caosErr := err.(type) { + case *caos_errs.AlreadyExistsError: + return codes.AlreadyExists, caosErr.GetMessage(), true + case *caos_errs.DeadlineExceededError: + return codes.DeadlineExceeded, caosErr.GetMessage(), true + case caos_errs.InternalError: + return codes.Internal, caosErr.GetMessage(), true + case *caos_errs.InvalidArgumentError: + return codes.InvalidArgument, caosErr.GetMessage(), true + case *caos_errs.NotFoundError: + return codes.NotFound, caosErr.GetMessage(), true + case *caos_errs.PermissionDeniedError: + return codes.PermissionDenied, caosErr.GetMessage(), true + case *caos_errs.PreconditionFailedError: + return codes.FailedPrecondition, caosErr.GetMessage(), true + case *caos_errs.UnauthenticatedError: + return codes.Unauthenticated, caosErr.GetMessage(), true + case *caos_errs.UnavailableError: + return codes.Unavailable, caosErr.GetMessage(), true + case *caos_errs.UnimplementedError: + return codes.Unimplemented, caosErr.GetMessage(), true + default: + return codes.Unknown, err.Error(), false + } +} diff --git a/internal/api/grpc/error_interceptor.go b/internal/api/grpc/error_interceptor.go new file mode 100644 index 0000000000..690ab9a2e9 --- /dev/null +++ b/internal/api/grpc/error_interceptor.go @@ -0,0 +1,14 @@ +package grpc + +import ( + "context" + + "google.golang.org/grpc" +) + +func ErrorHandler() func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + resp, err := handler(ctx, req) + return resp, CaosToGRPCError(err) + } +} diff --git a/internal/api/grpc/header.go b/internal/api/grpc/header.go new file mode 100644 index 0000000000..5d217b7518 --- /dev/null +++ b/internal/api/grpc/header.go @@ -0,0 +1,21 @@ +package grpc + +import ( + "context" + + "github.com/grpc-ecosystem/go-grpc-middleware/util/metautils" +) + +const ( + Authorization = "authorization" + + ZitadelOrgID = "x-zitadel-orgid" +) + +func GetHeader(ctx context.Context, headername string) string { + return metautils.ExtractIncoming(ctx).Get(headername) +} + +func GetAuthorizationHeader(ctx context.Context) string { + return GetHeader(ctx, Authorization) +} diff --git a/internal/api/grpc/probes.go b/internal/api/grpc/probes.go new file mode 100644 index 0000000000..8ec10c585c --- /dev/null +++ b/internal/api/grpc/probes.go @@ -0,0 +1,53 @@ +package grpc + +import ( + "context" + + "github.com/caos/logging" + "github.com/golang/protobuf/ptypes/empty" + structpb "github.com/golang/protobuf/ptypes/struct" + + "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/proto" +) + +type ValidationFunction func(ctx context.Context) error + +type Validator struct { + validations map[string]ValidationFunction +} + +func NewValidator(validations map[string]ValidationFunction) *Validator { + return &Validator{validations: validations} +} + +func (v *Validator) Healthz(_ context.Context, e *empty.Empty) (*empty.Empty, error) { + return e, nil +} + +func (v *Validator) Ready(ctx context.Context, e *empty.Empty) (*empty.Empty, error) { + return e, ready(ctx, v.validations) +} + +func (v *Validator) Validate(ctx context.Context, _ *empty.Empty) (*structpb.Struct, error) { + validations := validate(ctx, v.validations) + return proto.ToPBStruct(validations) +} + +func ready(ctx context.Context, validations map[string]ValidationFunction) error { + if len(validate(ctx, validations)) == 0 { + return nil + } + return errors.ThrowInternal(nil, "API-2jD9a", "not ready") +} + +func validate(ctx context.Context, validations map[string]ValidationFunction) map[string]error { + errors := make(map[string]error) + for id, validation := range validations { + if err := validation(ctx); err != nil { + logging.Log("API-vf823").WithError(err).Error("validation failed") + errors[id] = err + } + } + return errors +} diff --git a/internal/api/http/cookie.go b/internal/api/http/cookie.go new file mode 100644 index 0000000000..a28791aafc --- /dev/null +++ b/internal/api/http/cookie.go @@ -0,0 +1,125 @@ +package http + +import ( + "net/http" + + "github.com/gorilla/securecookie" + + "github.com/caos/zitadel/internal/errors" +) + +type CookieHandler struct { + securecookie *securecookie.SecureCookie + secureOnly bool + sameSite http.SameSite + path string + maxAge int + domain string +} + +func NewCookieHandler(opts ...CookieHandlerOpt) *CookieHandler { + c := &CookieHandler{ + secureOnly: true, + sameSite: http.SameSiteLaxMode, + path: "/", + } + + for _, opt := range opts { + opt(c) + } + return c +} + +type CookieHandlerOpt func(*CookieHandler) + +func WithEncryption(hashKey, encryptKey []byte) CookieHandlerOpt { + return func(c *CookieHandler) { + c.securecookie = securecookie.New(hashKey, encryptKey) + } +} + +func WithUnsecure() CookieHandlerOpt { + return func(c *CookieHandler) { + c.secureOnly = false + } +} + +func WithSameSite(sameSite http.SameSite) CookieHandlerOpt { + return func(c *CookieHandler) { + c.sameSite = sameSite + } +} + +func WithPath(path string) CookieHandlerOpt { + return func(c *CookieHandler) { + c.path = path + } +} + +func WithMaxAge(maxAge int) CookieHandlerOpt { + return func(c *CookieHandler) { + c.maxAge = maxAge + c.securecookie.MaxAge(maxAge) + } +} + +func WithDomain(domain string) CookieHandlerOpt { + return func(c *CookieHandler) { + c.domain = domain + } +} + +func (c *CookieHandler) GetCookieValue(r *http.Request, name string) (string, error) { + cookie, err := r.Cookie(name) + if err != nil { + return "", err + } + return cookie.Value, nil +} + +func (c *CookieHandler) GetEncryptedCookieValue(r *http.Request, name string, value interface{}) error { + cookie, err := r.Cookie(name) + if err != nil { + return err + } + if c.securecookie == nil { + return errors.ThrowInternal(nil, "HTTP-X6XpnL", "securecookie not configured") + } + if err := c.securecookie.Decode(name, cookie.Value, value); err != nil { + return err + } + return nil +} + +func (c *CookieHandler) SetCookie(w http.ResponseWriter, name string, value string) { + c.httpSet(w, name, value, c.maxAge) +} + +func (c *CookieHandler) SetEncryptedCookie(w http.ResponseWriter, name string, value interface{}) error { + if c.securecookie == nil { + return errors.ThrowInternal(nil, "HTTP-s2HUtx", "securecookie not configured") + } + encoded, err := c.securecookie.Encode(name, value) + if err != nil { + return err + } + c.httpSet(w, name, encoded, c.maxAge) + return nil +} + +func (c *CookieHandler) DeleteCookie(w http.ResponseWriter, name string) { + c.httpSet(w, name, "", -1) +} + +func (c *CookieHandler) httpSet(w http.ResponseWriter, name, value string, maxage int) { + http.SetCookie(w, &http.Cookie{ + Name: name, + Value: value, + Domain: c.domain, + Path: c.path, + MaxAge: maxage, + HttpOnly: true, + Secure: c.secureOnly, + SameSite: c.sameSite, + }) +} diff --git a/internal/api/http/parser.go b/internal/api/http/parser.go new file mode 100644 index 0000000000..fb24460e7d --- /dev/null +++ b/internal/api/http/parser.go @@ -0,0 +1,28 @@ +package http + +import ( + "net/http" + + "github.com/gorilla/schema" + + "github.com/caos/zitadel/internal/errors" +) + +type Parser struct { + decoder *schema.Decoder +} + +func NewParser() *Parser { + d := schema.NewDecoder() + d.IgnoreUnknownKeys(true) + return &Parser{d} +} + +func (p *Parser) Parse(r *http.Request, data interface{}) error { + err := r.ParseForm() + if err != nil { + return errors.ThrowInternal(err, "FORM-lCC9zI", "error parsing http form") + } + + return p.decoder.Decode(data, r.Form) +} diff --git a/internal/proto/struct.go b/internal/proto/struct.go new file mode 100644 index 0000000000..24a6ce0e36 --- /dev/null +++ b/internal/proto/struct.go @@ -0,0 +1,52 @@ +package proto + +import ( + "bytes" + "encoding/json" + + "github.com/golang/protobuf/jsonpb" + pb_struct "github.com/golang/protobuf/ptypes/struct" + + "github.com/caos/logging" +) + +func MustToPBStruct(object interface{}) *pb_struct.Struct { + s, err := ToPBStruct(object) + logging.Log("PROTO-7Aa3t").OnError(err).Panic("unable to map object to pb-struct") + + return s +} + +func BytesToPBStruct(b []byte) (*pb_struct.Struct, error) { + fields := new(pb_struct.Struct) + err := jsonpb.Unmarshal(bytes.NewReader(b), fields) + return fields, err +} + +func ToPBStruct(object interface{}) (*pb_struct.Struct, error) { + fields := new(pb_struct.Struct) + + marshalled, err := json.Marshal(object) + if err != nil { + return nil, err + } + + err = jsonpb.Unmarshal(bytes.NewReader(marshalled), fields) + + return fields, err +} + +func MustFromPBStruct(object interface{}, s *pb_struct.Struct) { + err := FromPBStruct(object, s) + logging.Log("PROTO-WeMYY").OnError(err).Panic("unable to map pb-struct into object") +} + +func FromPBStruct(object interface{}, s *pb_struct.Struct) error { + marshaller := new(jsonpb.Marshaler) + jsonString, err := marshaller.MarshalToString(s) + if err != nil { + return err + } + + return json.Unmarshal([]byte(jsonString), object) +} diff --git a/internal/proto/struct_test.go b/internal/proto/struct_test.go new file mode 100644 index 0000000000..eeed7c63f3 --- /dev/null +++ b/internal/proto/struct_test.go @@ -0,0 +1,53 @@ +package proto + +import ( + "testing" + + pb_struct "github.com/golang/protobuf/ptypes/struct" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestToPBStruct(t *testing.T) { + obj := struct { + ID string + Name string + Seq uint64 + }{ + ID: "asdf", + Name: "ueli", + Seq: 208582075, + } + fields, err := ToPBStruct(&obj) + require.NoError(t, err) + require.Len(t, fields.Fields, 3) + + assert.Equal(t, obj.ID, fields.Fields["ID"].GetStringValue()) + assert.Equal(t, int(obj.Seq), int(fields.Fields["Seq"].GetNumberValue())) + assert.Equal(t, obj.Name, fields.Fields["Name"].GetStringValue()) +} + +func TestFromPBStruct(t *testing.T) { + name := "ueli" + id := "asdf" + seq := float64(208582075) + s := &pb_struct.Struct{Fields: map[string]*pb_struct.Value{ + "ID": &pb_struct.Value{Kind: &pb_struct.Value_StringValue{StringValue: id}}, + "Name": &pb_struct.Value{Kind: &pb_struct.Value_StringValue{StringValue: name}}, + "Seq": &pb_struct.Value{Kind: &pb_struct.Value_NumberValue{NumberValue: seq}}, + }} + + obj := struct { + ID string + Name string + Seq uint64 + }{} + + err := FromPBStruct(&obj, s) + require.NoError(t, err) + + assert.Equal(t, id, obj.ID) + assert.Equal(t, name, obj.Name) + assert.Equal(t, int(seq), int(obj.Seq)) +} From 90342ed872df532c17aae0c83227f601661e3ce3 Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Mon, 23 Mar 2020 07:06:44 +0100 Subject: [PATCH 10/39] feat: add crypto pkg --- internal/crypto/aes.go | 136 ++++++++++++++++ internal/crypto/aes_test.go | 17 ++ internal/crypto/bcrypt.go | 27 ++++ internal/crypto/code.go | 153 ++++++++++++++++++ internal/crypto/code_test.go | 92 +++++++++++ internal/crypto/crypto.go | 103 +++++++++++++ internal/crypto/crypto_mock.go | 223 +++++++++++++++++++++++++++ internal/crypto/crypto_test.go | 273 +++++++++++++++++++++++++++++++++ internal/crypto/generate.go | 3 + internal/crypto/key.go | 64 ++++++++ 10 files changed, 1091 insertions(+) create mode 100644 internal/crypto/aes.go create mode 100644 internal/crypto/aes_test.go create mode 100644 internal/crypto/bcrypt.go create mode 100644 internal/crypto/code.go create mode 100644 internal/crypto/code_test.go create mode 100644 internal/crypto/crypto.go create mode 100644 internal/crypto/crypto_mock.go create mode 100644 internal/crypto/crypto_test.go create mode 100644 internal/crypto/generate.go create mode 100644 internal/crypto/key.go diff --git a/internal/crypto/aes.go b/internal/crypto/aes.go new file mode 100644 index 0000000000..31d3e46847 --- /dev/null +++ b/internal/crypto/aes.go @@ -0,0 +1,136 @@ +package crypto + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "encoding/base64" + "io" + + "github.com/caos/zitadel/internal/errors" +) + +var _ EncryptionAlg = (*AESCrypto)(nil) + +type AESCrypto struct { + keys map[string]string + encryptionKeyID string + keyIDs []string +} + +func NewAESCrypto(config *KeyConfig) (*AESCrypto, error) { + keys, ids, err := LoadKeys(config) + if err != nil { + return nil, err + } + return &AESCrypto{ + keys: keys, + encryptionKeyID: config.EncryptionKeyID, + keyIDs: ids, + }, nil +} + +func (a *AESCrypto) Algorithm() string { + return "aes" +} + +func (a *AESCrypto) Encrypt(value []byte) ([]byte, error) { + return EncryptAES(value, a.encryptionKey()) +} + +func (a *AESCrypto) Decrypt(value []byte, keyID string) ([]byte, error) { + key, err := a.decryptionKey(keyID) + if err != nil { + return nil, err + } + return DecryptAES(value, key) +} + +func (a *AESCrypto) DecryptString(value []byte, keyID string) (string, error) { + key, err := a.decryptionKey(keyID) + if err != nil { + return "", err + } + b, err := DecryptAES(value, key) + if err != nil { + return "", err + } + return string(b), nil +} + +func (a *AESCrypto) EncryptionKeyID() string { + return a.encryptionKeyID +} + +func (a *AESCrypto) DecryptionKeyIDs() []string { + return a.keyIDs +} + +func (a *AESCrypto) encryptionKey() string { + return a.keys[a.encryptionKeyID] +} + +func (a *AESCrypto) decryptionKey(keyID string) (string, error) { + key, ok := a.keys[keyID] + if !ok { + return "", errors.ThrowNotFound(nil, "CRYPT-nkj1s", "unknown key id") + } + return key, nil +} + +func EncryptAESString(data string, key string) (string, error) { + encrypted, err := EncryptAES([]byte(data), key) + if err != nil { + return "", err + } + return base64.URLEncoding.EncodeToString(encrypted), nil +} + +func EncryptAES(plainText []byte, key string) ([]byte, error) { + block, err := aes.NewCipher([]byte(key)) + if err != nil { + return nil, err + } + + cipherText := make([]byte, aes.BlockSize+len(plainText)) + iv := cipherText[:aes.BlockSize] + if _, err = io.ReadFull(rand.Reader, iv); err != nil { + return nil, err + } + + stream := cipher.NewCFBEncrypter(block, iv) + stream.XORKeyStream(cipherText[aes.BlockSize:], plainText) + + return cipherText, nil +} + +func DecryptAESString(data string, key string) (string, error) { + text, err := base64.URLEncoding.DecodeString(data) + if err != nil { + return "", nil + } + decrypted, err := DecryptAES(text, key) + if err != nil { + return "", err + } + return string(decrypted), nil +} + +func DecryptAES(cipherText []byte, key string) ([]byte, error) { + block, err := aes.NewCipher([]byte(key)) + if err != nil { + return nil, err + } + + if len(cipherText) < aes.BlockSize { + err = errors.ThrowPreconditionFailed(nil, "CRYPT-23kH1", "cipher text block too short") + return nil, err + } + iv := cipherText[:aes.BlockSize] + cipherText = cipherText[aes.BlockSize:] + + stream := cipher.NewCFBDecrypter(block, iv) + stream.XORKeyStream(cipherText, cipherText) + + return cipherText, err +} diff --git a/internal/crypto/aes_test.go b/internal/crypto/aes_test.go new file mode 100644 index 0000000000..c7e31de3d5 --- /dev/null +++ b/internal/crypto/aes_test.go @@ -0,0 +1,17 @@ +package crypto + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestDecrypt_OK(t *testing.T) { + encryptedpw, err := EncryptAESString("ThisIsMySecretPw", "passphrasewhichneedstobe32bytes!") + assert.NoError(t, err) + + decryptedpw, err := DecryptAESString(encryptedpw, "passphrasewhichneedstobe32bytes!") + assert.NoError(t, err) + + assert.Equal(t, "ThisIsMySecretPw", decryptedpw) +} diff --git a/internal/crypto/bcrypt.go b/internal/crypto/bcrypt.go new file mode 100644 index 0000000000..e7daffb27d --- /dev/null +++ b/internal/crypto/bcrypt.go @@ -0,0 +1,27 @@ +package crypto + +import ( + "golang.org/x/crypto/bcrypt" +) + +var _ HashAlg = (*BCrypt)(nil) + +type BCrypt struct { + cost int +} + +func NewBCrypt(cost int) *BCrypt { + return &BCrypt{cost: cost} +} + +func (b *BCrypt) Algorithm() string { + return "bcrypt" +} + +func (b *BCrypt) Hash(value []byte) ([]byte, error) { + return bcrypt.GenerateFromPassword(value, b.cost) +} + +func (b *BCrypt) CompareHash(hashed, value []byte) error { + return bcrypt.CompareHashAndPassword(hashed, value) +} diff --git a/internal/crypto/code.go b/internal/crypto/code.go new file mode 100644 index 0000000000..0537710da6 --- /dev/null +++ b/internal/crypto/code.go @@ -0,0 +1,153 @@ +package crypto + +import ( + "crypto/rand" + "time" + + "github.com/caos/zitadel/internal/errors" +) + +var ( + LowerLetters = []rune("abcdefghijklmnopqrstuvwxyz") + UpperLetters = []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZ") + Digits = []rune("0123456789") + Symbols = []rune("~!@#$^&*()_+`-={}|[]:<>?,./") +) + +type Generator interface { + Length() uint + Expiry() time.Duration + Alg() Crypto + Runes() []rune +} + +type EncryptionGenerator struct { + length uint + expiry time.Duration + alg EncryptionAlg + runes []rune +} + +func (g *EncryptionGenerator) Length() uint { + return g.length +} + +func (g *EncryptionGenerator) Expiry() time.Duration { + return g.expiry +} + +func (g *EncryptionGenerator) Alg() Crypto { + return g.alg +} + +func (g *EncryptionGenerator) Runes() []rune { + return g.runes +} + +func NewEncryptionGenerator(length uint, expiry time.Duration, alg EncryptionAlg, runes []rune) *EncryptionGenerator { + return &EncryptionGenerator{ + length: length, + expiry: expiry, + alg: alg, + runes: runes, + } +} + +type HashGenerator struct { + length uint + expiry time.Duration + alg HashAlg + runes []rune +} + +func (g *HashGenerator) Length() uint { + return g.length +} + +func (g *HashGenerator) Expiry() time.Duration { + return g.expiry +} + +func (g *HashGenerator) Alg() Crypto { + return g.alg +} + +func (g *HashGenerator) Runes() []rune { + return g.runes +} + +func NewHashGenerator(length uint, expiry time.Duration, alg HashAlg, runes []rune) *HashGenerator { + return &HashGenerator{ + length: length, + expiry: expiry, + alg: alg, + runes: runes, + } +} + +func NewCode(g Generator) (*CryptoValue, string, error) { + code, err := generateRandomString(g.Length(), g.Runes()) + if err != nil { + return nil, "", err + } + crypto, err := Crypt([]byte(code), g.Alg()) + if err != nil { + return nil, "", err + } + return crypto, code, nil +} + +func IsCodeExpired(creationDate time.Time, expiry time.Duration) bool { + return creationDate.Add(expiry).Before(time.Now().UTC()) +} + +func VerifyCode(creationDate time.Time, expiry time.Duration, cryptoCode *CryptoValue, verificationCode string, g Generator) error { + if IsCodeExpired(creationDate, expiry) { + return errors.ThrowPreconditionFailed(nil, "CODE-QvUQ4P", "verification code is expired") + } + switch alg := g.Alg().(type) { + case EncryptionAlg: + return verifyEncryptedCode(cryptoCode, verificationCode, alg) + case HashAlg: + return verifyHashedCode(cryptoCode, verificationCode, alg) + } + return errors.ThrowInvalidArgument(nil, "CODE-fW2gNa", "generator alg is not supported") +} + +func generateRandomString(length uint, chars []rune) (string, error) { + if length == 0 { + return "", nil + } + + max := len(chars) - 1 + maxStr := int(length - 1) + + str := make([]rune, length) + randBytes := make([]byte, length) + if _, err := rand.Read(randBytes); err != nil { + return "", err + } + for i, rb := range randBytes { + str[i] = chars[int(rb)%max] + if i == maxStr { + return string(str), nil + } + } + return "", nil +} + +func verifyEncryptedCode(cryptoCode *CryptoValue, verificationCode string, alg EncryptionAlg) error { + code, err := DecryptString(cryptoCode, alg) + if err != nil { + return err + } + + if code != verificationCode { + return errors.ThrowInvalidArgument(nil, "CODE-woT0xc", "verification code is invalid") + } + return nil +} + +func verifyHashedCode(cryptoCode *CryptoValue, verificationCode string, alg HashAlg) error { + return CompareHash(cryptoCode, []byte(verificationCode), alg) +} diff --git a/internal/crypto/code_test.go b/internal/crypto/code_test.go new file mode 100644 index 0000000000..f7f55390e7 --- /dev/null +++ b/internal/crypto/code_test.go @@ -0,0 +1,92 @@ +package crypto + +import ( + "testing" + "time" + + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/assert" +) + +func Test_Encrypted_OK(t *testing.T) { + mCrypto := NewMockEncryptionAlg(gomock.NewController(t)) + mCrypto.EXPECT().Algorithm().AnyTimes().Return("enc") + mCrypto.EXPECT().EncryptionKeyID().AnyTimes().Return("id") + mCrypto.EXPECT().DecryptionKeyIDs().AnyTimes().Return([]string{"id"}) + mCrypto.EXPECT().Encrypt(gomock.Any()).DoAndReturn( + func(code []byte) ([]byte, error) { + return code, nil + }, + ) + mCrypto.EXPECT().DecryptString(gomock.Any(), gomock.Any()).DoAndReturn( + func(code []byte, _ string) (string, error) { + return string(code), nil + }, + ) + generator := NewEncryptionGenerator(6, 0, mCrypto, Digits) + + crypto, code, err := NewCode(generator) + assert.NoError(t, err) + + decrypted, err := DecryptString(crypto, generator.alg) + assert.NoError(t, err) + assert.Equal(t, code, decrypted) + assert.Equal(t, 6, len(decrypted)) +} + +func Test_Verify_Encrypted_OK(t *testing.T) { + mCrypto := NewMockEncryptionAlg(gomock.NewController(t)) + mCrypto.EXPECT().Algorithm().AnyTimes().Return("enc") + mCrypto.EXPECT().EncryptionKeyID().AnyTimes().Return("id") + mCrypto.EXPECT().DecryptionKeyIDs().AnyTimes().Return([]string{"id"}) + mCrypto.EXPECT().DecryptString(gomock.Any(), gomock.Any()).DoAndReturn( + func(code []byte, _ string) (string, error) { + return string(code), nil + }, + ) + creationDate := time.Now() + code := &CryptoValue{ + CryptoType: TypeEncryption, + Algorithm: "enc", + KeyID: "id", + Crypted: []byte("code"), + } + generator := NewEncryptionGenerator(6, 0, mCrypto, Digits) + + err := VerifyCode(creationDate, 1*time.Hour, code, "code", generator) + assert.NoError(t, err) +} +func Test_Verify_Encrypted_Invalid_Err(t *testing.T) { + mCrypto := NewMockEncryptionAlg(gomock.NewController(t)) + mCrypto.EXPECT().Algorithm().AnyTimes().Return("enc") + mCrypto.EXPECT().EncryptionKeyID().AnyTimes().Return("id") + mCrypto.EXPECT().DecryptionKeyIDs().AnyTimes().Return([]string{"id"}) + mCrypto.EXPECT().DecryptString(gomock.Any(), gomock.Any()).DoAndReturn( + func(code []byte, _ string) (string, error) { + return string(code), nil + }, + ) + creationDate := time.Now() + code := &CryptoValue{ + CryptoType: TypeEncryption, + Algorithm: "enc", + KeyID: "id", + Crypted: []byte("code"), + } + generator := NewEncryptionGenerator(6, 0, mCrypto, Digits) + + err := VerifyCode(creationDate, 1*time.Hour, code, "wrong", generator) + assert.Error(t, err) +} + +func TestIsCodeExpired_Expired(t *testing.T) { + creationDate := time.Date(2019, time.April, 1, 0, 0, 0, 0, time.UTC) + expired := IsCodeExpired(creationDate, 1*time.Hour) + assert.True(t, expired) +} + +func TestIsCodeExpired_NotExpired(t *testing.T) { + creationDate := time.Now() + expired := IsCodeExpired(creationDate, 1*time.Hour) + assert.False(t, expired) +} diff --git a/internal/crypto/crypto.go b/internal/crypto/crypto.go new file mode 100644 index 0000000000..38ee06577b --- /dev/null +++ b/internal/crypto/crypto.go @@ -0,0 +1,103 @@ +package crypto + +import ( + "github.com/caos/zitadel/internal/errors" +) + +const ( + TypeEncryption CryptoType = iota + TypeHash +) + +type Crypto interface { + Algorithm() string +} + +type EncryptionAlg interface { + Crypto + EncryptionKeyID() string + DecryptionKeyIDs() []string + Encrypt(value []byte) ([]byte, error) + Decrypt(hashed []byte, keyID string) ([]byte, error) + DecryptString(hashed []byte, keyID string) (string, error) +} + +type HashAlg interface { + Crypto + Hash(value []byte) ([]byte, error) + CompareHash(hashed, comparer []byte) error +} + +type CryptoValue struct { + CryptoType CryptoType + Algorithm string + KeyID string + Crypted []byte +} + +type CryptoType int + +func Crypt(value []byte, c Crypto) (*CryptoValue, error) { + switch alg := c.(type) { + case EncryptionAlg: + return Encrypt(value, alg) + case HashAlg: + return Hash(value, alg) + } + return nil, errors.ThrowInternal(nil, "CRYPT-r4IaHZ", "algorithm not supported") +} + +func Encrypt(value []byte, alg EncryptionAlg) (*CryptoValue, error) { + encrypted, err := alg.Encrypt(value) + if err != nil { + return nil, errors.ThrowInternal(err, "CRYPT-qCD0JB", "error encrypting value") + } + return &CryptoValue{ + CryptoType: TypeEncryption, + Algorithm: alg.Algorithm(), + KeyID: alg.EncryptionKeyID(), + Crypted: encrypted, + }, nil +} + +func Decrypt(value *CryptoValue, alg EncryptionAlg) ([]byte, error) { + if err := checkEncAlg(value, alg); err != nil { + return nil, err + } + return alg.Decrypt(value.Crypted, value.KeyID) +} + +func DecryptString(value *CryptoValue, alg EncryptionAlg) (string, error) { + if err := checkEncAlg(value, alg); err != nil { + return "", err + } + return alg.DecryptString(value.Crypted, value.KeyID) +} + +func checkEncAlg(value *CryptoValue, alg EncryptionAlg) error { + if value.Algorithm != alg.Algorithm() { + return errors.ThrowInvalidArgument(nil, "CRYPT-Nx7XlT", "value was encrypted with a different key") + } + for _, id := range alg.DecryptionKeyIDs() { + if id == value.KeyID { + return nil + } + } + return errors.ThrowInvalidArgument(nil, "CRYPT-Kq12vn", "value was encrypted with a different key") +} + +func Hash(value []byte, alg HashAlg) (*CryptoValue, error) { + hashed, err := alg.Hash(value) + if err != nil { + return nil, errors.ThrowInternal(err, "CRYPT-rBVaJU", "error hashing value") + } + return &CryptoValue{ + CryptoType: TypeHash, + Algorithm: alg.Algorithm(), + Crypted: hashed, + }, nil +} + +func CompareHash(value *CryptoValue, comparer []byte, alg HashAlg) error { + return alg.CompareHash(value.Crypted, comparer) +} diff --git a/internal/crypto/crypto_mock.go b/internal/crypto/crypto_mock.go new file mode 100644 index 0000000000..3785c285ae --- /dev/null +++ b/internal/crypto/crypto_mock.go @@ -0,0 +1,223 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: crypto.go + +// Package crypto is a generated GoMock package. +package crypto + +import ( + gomock "github.com/golang/mock/gomock" + reflect "reflect" +) + +// MockCrypto is a mock of Crypto interface +type MockCrypto struct { + ctrl *gomock.Controller + recorder *MockCryptoMockRecorder +} + +// MockCryptoMockRecorder is the mock recorder for MockCrypto +type MockCryptoMockRecorder struct { + mock *MockCrypto +} + +// NewMockCrypto creates a new mock instance +func NewMockCrypto(ctrl *gomock.Controller) *MockCrypto { + mock := &MockCrypto{ctrl: ctrl} + mock.recorder = &MockCryptoMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockCrypto) EXPECT() *MockCryptoMockRecorder { + return m.recorder +} + +// Algorithm mocks base method +func (m *MockCrypto) Algorithm() string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Algorithm") + ret0, _ := ret[0].(string) + return ret0 +} + +// Algorithm indicates an expected call of Algorithm +func (mr *MockCryptoMockRecorder) Algorithm() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Algorithm", reflect.TypeOf((*MockCrypto)(nil).Algorithm)) +} + +// MockEncryptionAlg is a mock of EncryptionAlg interface +type MockEncryptionAlg struct { + ctrl *gomock.Controller + recorder *MockEncryptionAlgMockRecorder +} + +// MockEncryptionAlgMockRecorder is the mock recorder for MockEncryptionAlg +type MockEncryptionAlgMockRecorder struct { + mock *MockEncryptionAlg +} + +// NewMockEncryptionAlg creates a new mock instance +func NewMockEncryptionAlg(ctrl *gomock.Controller) *MockEncryptionAlg { + mock := &MockEncryptionAlg{ctrl: ctrl} + mock.recorder = &MockEncryptionAlgMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockEncryptionAlg) EXPECT() *MockEncryptionAlgMockRecorder { + return m.recorder +} + +// Algorithm mocks base method +func (m *MockEncryptionAlg) Algorithm() string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Algorithm") + ret0, _ := ret[0].(string) + return ret0 +} + +// Algorithm indicates an expected call of Algorithm +func (mr *MockEncryptionAlgMockRecorder) Algorithm() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Algorithm", reflect.TypeOf((*MockEncryptionAlg)(nil).Algorithm)) +} + +// EncryptionKeyID mocks base method +func (m *MockEncryptionAlg) EncryptionKeyID() string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "EncryptionKeyID") + ret0, _ := ret[0].(string) + return ret0 +} + +// EncryptionKeyID indicates an expected call of EncryptionKeyID +func (mr *MockEncryptionAlgMockRecorder) EncryptionKeyID() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EncryptionKeyID", reflect.TypeOf((*MockEncryptionAlg)(nil).EncryptionKeyID)) +} + +// DecryptionKeyIDs mocks base method +func (m *MockEncryptionAlg) DecryptionKeyIDs() []string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DecryptionKeyIDs") + ret0, _ := ret[0].([]string) + return ret0 +} + +// DecryptionKeyIDs indicates an expected call of DecryptionKeyIDs +func (mr *MockEncryptionAlgMockRecorder) DecryptionKeyIDs() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DecryptionKeyIDs", reflect.TypeOf((*MockEncryptionAlg)(nil).DecryptionKeyIDs)) +} + +// Encrypt mocks base method +func (m *MockEncryptionAlg) Encrypt(value []byte) ([]byte, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Encrypt", value) + ret0, _ := ret[0].([]byte) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Encrypt indicates an expected call of Encrypt +func (mr *MockEncryptionAlgMockRecorder) Encrypt(value interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Encrypt", reflect.TypeOf((*MockEncryptionAlg)(nil).Encrypt), value) +} + +// Decrypt mocks base method +func (m *MockEncryptionAlg) Decrypt(hashed []byte, keyID string) ([]byte, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Decrypt", hashed, keyID) + ret0, _ := ret[0].([]byte) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Decrypt indicates an expected call of Decrypt +func (mr *MockEncryptionAlgMockRecorder) Decrypt(hashed, keyID interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Decrypt", reflect.TypeOf((*MockEncryptionAlg)(nil).Decrypt), hashed, keyID) +} + +// DecryptString mocks base method +func (m *MockEncryptionAlg) DecryptString(hashed []byte, keyID string) (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DecryptString", hashed, keyID) + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DecryptString indicates an expected call of DecryptString +func (mr *MockEncryptionAlgMockRecorder) DecryptString(hashed, keyID interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DecryptString", reflect.TypeOf((*MockEncryptionAlg)(nil).DecryptString), hashed, keyID) +} + +// MockHashAlg is a mock of HashAlg interface +type MockHashAlg struct { + ctrl *gomock.Controller + recorder *MockHashAlgMockRecorder +} + +// MockHashAlgMockRecorder is the mock recorder for MockHashAlg +type MockHashAlgMockRecorder struct { + mock *MockHashAlg +} + +// NewMockHashAlg creates a new mock instance +func NewMockHashAlg(ctrl *gomock.Controller) *MockHashAlg { + mock := &MockHashAlg{ctrl: ctrl} + mock.recorder = &MockHashAlgMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockHashAlg) EXPECT() *MockHashAlgMockRecorder { + return m.recorder +} + +// Algorithm mocks base method +func (m *MockHashAlg) Algorithm() string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Algorithm") + ret0, _ := ret[0].(string) + return ret0 +} + +// Algorithm indicates an expected call of Algorithm +func (mr *MockHashAlgMockRecorder) Algorithm() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Algorithm", reflect.TypeOf((*MockHashAlg)(nil).Algorithm)) +} + +// Hash mocks base method +func (m *MockHashAlg) Hash(value []byte) ([]byte, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Hash", value) + ret0, _ := ret[0].([]byte) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Hash indicates an expected call of Hash +func (mr *MockHashAlgMockRecorder) Hash(value interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Hash", reflect.TypeOf((*MockHashAlg)(nil).Hash), value) +} + +// CompareHash mocks base method +func (m *MockHashAlg) CompareHash(hashed, comparer []byte) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CompareHash", hashed, comparer) + ret0, _ := ret[0].(error) + return ret0 +} + +// CompareHash indicates an expected call of CompareHash +func (mr *MockHashAlgMockRecorder) CompareHash(hashed, comparer interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CompareHash", reflect.TypeOf((*MockHashAlg)(nil).CompareHash), hashed, comparer) +} diff --git a/internal/crypto/crypto_test.go b/internal/crypto/crypto_test.go new file mode 100644 index 0000000000..76334884b9 --- /dev/null +++ b/internal/crypto/crypto_test.go @@ -0,0 +1,273 @@ +package crypto + +import ( + "bytes" + "errors" + "reflect" + "testing" +) + +type mockEncCrypto struct { +} + +func (m *mockEncCrypto) Algorithm() string { + return "enc" +} + +func (m *mockEncCrypto) Encrypt(value []byte) ([]byte, error) { + return value, nil +} + +func (m *mockEncCrypto) Decrypt(value []byte, _ string) ([]byte, error) { + return value, nil +} + +func (m *mockEncCrypto) DecryptString(value []byte, _ string) (string, error) { + return string(value), nil +} + +func (m *mockEncCrypto) EncryptionKeyID() string { + return "keyID" +} +func (m *mockEncCrypto) DecryptionKeyIDs() []string { + return []string{"keyID"} +} + +type mockHashCrypto struct { +} + +func (m *mockHashCrypto) Algorithm() string { + return "hash" +} + +func (m *mockHashCrypto) Hash(value []byte) ([]byte, error) { + return value, nil +} + +func (m *mockHashCrypto) CompareHash(hashed, comparer []byte) error { + if !bytes.Equal(hashed, comparer) { + return errors.New("not equal") + } + return nil +} + +type alg struct{} + +func (a *alg) Algorithm() string { + return "alg" +} + +func TestCrypt(t *testing.T) { + type args struct { + value []byte + c Crypto + } + tests := []struct { + name string + args args + want *CryptoValue + wantErr bool + }{ + { + "encrypt", + args{[]byte("test"), &mockEncCrypto{}}, + &CryptoValue{CryptoType: TypeEncryption, Algorithm: "enc", KeyID: "keyID", Crypted: []byte("test")}, + false, + }, + { + "hash", + args{[]byte("test"), &mockHashCrypto{}}, + &CryptoValue{CryptoType: TypeHash, Algorithm: "hash", Crypted: []byte("test")}, + false, + }, + { + "wrong type", + args{[]byte("test"), &alg{}}, + nil, + true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := Crypt(tt.args.value, tt.args.c) + if (err != nil) != tt.wantErr { + t.Errorf("Crypt() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("Crypt() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestEncrypt(t *testing.T) { + type args struct { + value []byte + c EncryptionAlg + } + tests := []struct { + name string + args args + want *CryptoValue + wantErr bool + }{ + { + "ok", + args{[]byte("test"), &mockEncCrypto{}}, + &CryptoValue{CryptoType: TypeEncryption, Algorithm: "enc", KeyID: "keyID", Crypted: []byte("test")}, + false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := Encrypt(tt.args.value, tt.args.c) + if (err != nil) != tt.wantErr { + t.Errorf("Encrypt() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("Encrypt() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestDecrypt(t *testing.T) { + type args struct { + value *CryptoValue + c EncryptionAlg + } + tests := []struct { + name string + args args + want []byte + wantErr bool + }{ + { + "ok", + args{&CryptoValue{CryptoType: TypeEncryption, Algorithm: "enc", KeyID: "keyID", Crypted: []byte("test")}, &mockEncCrypto{}}, + []byte("test"), + false, + }, + { + "wrong id", + args{&CryptoValue{CryptoType: TypeEncryption, Algorithm: "enc", KeyID: "keyID2", Crypted: []byte("test")}, &mockEncCrypto{}}, + nil, + true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := Decrypt(tt.args.value, tt.args.c) + if (err != nil) != tt.wantErr { + t.Errorf("Decrypt() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("Decrypt() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestDecryptString(t *testing.T) { + type args struct { + value *CryptoValue + c EncryptionAlg + } + tests := []struct { + name string + args args + want string + wantErr bool + }{ + { + "ok", + args{&CryptoValue{CryptoType: TypeEncryption, Algorithm: "enc", KeyID: "keyID", Crypted: []byte("test")}, &mockEncCrypto{}}, + "test", + false, + }, + { + "wrong id", + args{&CryptoValue{CryptoType: TypeEncryption, Algorithm: "enc", KeyID: "keyID2", Crypted: []byte("test")}, &mockEncCrypto{}}, + "", + true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := DecryptString(tt.args.value, tt.args.c) + if (err != nil) != tt.wantErr { + t.Errorf("DecryptString() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("DecryptString() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestHash(t *testing.T) { + type args struct { + value []byte + c HashAlg + } + tests := []struct { + name string + args args + want *CryptoValue + wantErr bool + }{ + { + "ok", + args{[]byte("test"), &mockHashCrypto{}}, + &CryptoValue{CryptoType: TypeHash, Algorithm: "hash", Crypted: []byte("test")}, + false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := Hash(tt.args.value, tt.args.c) + if (err != nil) != tt.wantErr { + t.Errorf("Hash() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("Hash() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestCompareHash(t *testing.T) { + type args struct { + value *CryptoValue + comparer []byte + c HashAlg + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + "ok", + args{&CryptoValue{CryptoType: TypeHash, Algorithm: "hash", Crypted: []byte("test")}, []byte("test"), &mockHashCrypto{}}, + false, + }, + { + "wrong", + args{&CryptoValue{CryptoType: TypeHash, Algorithm: "hash", Crypted: []byte("test")}, []byte("test2"), &mockHashCrypto{}}, + true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := CompareHash(tt.args.value, tt.args.comparer, tt.args.c); (err != nil) != tt.wantErr { + t.Errorf("CompareHash() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/crypto/generate.go b/internal/crypto/generate.go new file mode 100644 index 0000000000..4c43e7e9b3 --- /dev/null +++ b/internal/crypto/generate.go @@ -0,0 +1,3 @@ +package crypto + +//go:generate mockgen -source crypto.go -destination ./crypto_mock.go -package crypto diff --git a/internal/crypto/key.go b/internal/crypto/key.go new file mode 100644 index 0000000000..da7f6de9b9 --- /dev/null +++ b/internal/crypto/key.go @@ -0,0 +1,64 @@ +package crypto + +import ( + "os" + + "github.com/caos/logging" + "github.com/caos/utils/errors" + + "github.com/caos/zitadel/internal/config" +) + +const ( + ZitadelKeyPath = "ZITADEL_KEY_PATH" +) + +type KeyConfig struct { + EncryptionKeyID string + DecryptionKeyIDs []string + Path string +} + +type Keys map[string]string + +func ReadKeys(path string) (Keys, error) { + if path == "" { + path = os.Getenv(ZitadelKeyPath) + if path == "" { + return nil, errors.ThrowInvalidArgument(nil, "CRYPT-56lka", "no path set") + } + } + keys := new(Keys) + err := config.Read(keys, path) + return *keys, err +} + +func LoadKeys(config *KeyConfig) (map[string]string, []string, error) { + if config == nil { + return nil, nil, errors.ThrowInvalidArgument(nil, "CRYPT-dJK8s", "config must not be nil") + } + readKeys, err := ReadKeys(config.Path) + if err != nil { + return nil, nil, err + } + keys := make(map[string]string) + ids := make([]string, 0, len(config.DecryptionKeyIDs)+1) + if config.EncryptionKeyID != "" { + key, ok := readKeys[config.EncryptionKeyID] + if !ok { + return nil, nil, errors.ThrowInternalf(nil, "CRYPT-v2Kas", "encryption key not found") + } + keys[config.EncryptionKeyID] = key + ids = append(ids, config.EncryptionKeyID) + } + for _, id := range config.DecryptionKeyIDs { + key, ok := readKeys[id] + if !ok { + logging.Log("CRYPT-s23rf").Warnf("description key %s not found", id) + continue + } + keys[id] = key + ids = append(ids, id) + } + return keys, ids, nil +} From 265ea450b1b198d4a9668467a18ad9953b77ba23 Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Mon, 23 Mar 2020 08:43:08 +0100 Subject: [PATCH 11/39] fix: import --- go.mod | 1 - go.sum | 2 -- internal/crypto/key.go | 2 +- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/go.mod b/go.mod index d6ffe46cdf..3c67100f96 100644 --- a/go.mod +++ b/go.mod @@ -22,5 +22,4 @@ require ( google.golang.org/grpc v1.28.0 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect gopkg.in/yaml.v2 v2.2.8 // indirect - rsc.io/sampler v1.99.99 // indirect ) diff --git a/go.sum b/go.sum index f39134d478..6e39a2d0fe 100644 --- a/go.sum +++ b/go.sum @@ -131,5 +131,3 @@ rsc.io/quote/v3 v3.1.0 h1:9JKUTTIUgS6kzR9mK1YuGKv6Nl+DijDNIc0ghT58FaY= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -rsc.io/sampler v1.99.99 h1:7i08f/p5TBU5joCPW3GjWG1ZFCmr28ybGqlXtelhEK8= -rsc.io/sampler v1.99.99/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/internal/crypto/key.go b/internal/crypto/key.go index da7f6de9b9..2d48ff870a 100644 --- a/internal/crypto/key.go +++ b/internal/crypto/key.go @@ -4,9 +4,9 @@ import ( "os" "github.com/caos/logging" - "github.com/caos/utils/errors" "github.com/caos/zitadel/internal/config" + "github.com/caos/zitadel/internal/errors" ) const ( From 781e8b215e30c4559b54a6643764ae4a521a713c Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Mon, 23 Mar 2020 11:53:12 +0100 Subject: [PATCH 12/39] feat: add protoc pkg --- go.mod | 11 + go.sum | 27 ++ internal/protoc/protoc-base/protoc_helper.go | 112 +++++++++ internal/protoc/protoc-base/templates.go | 106 ++++++++ .../protoc/protoc-gen-authoption/README.md | 37 +++ .../authoption/generate.go | 3 + .../authoption/options.pb.go | 105 ++++++++ .../authoption/options.proto | 17 ++ .../protoc/protoc-gen-authoption/generate.go | 4 + internal/protoc/protoc-gen-authoption/main.go | 15 ++ .../protoc/protoc-gen-authoption/templates.go | 237 ++++++++++++++++++ .../templates/auth_method_mapping.go.tmpl | 35 +++ 12 files changed, 709 insertions(+) create mode 100644 internal/protoc/protoc-base/protoc_helper.go create mode 100644 internal/protoc/protoc-base/templates.go create mode 100644 internal/protoc/protoc-gen-authoption/README.md create mode 100644 internal/protoc/protoc-gen-authoption/authoption/generate.go create mode 100644 internal/protoc/protoc-gen-authoption/authoption/options.pb.go create mode 100644 internal/protoc/protoc-gen-authoption/authoption/options.proto create mode 100644 internal/protoc/protoc-gen-authoption/generate.go create mode 100644 internal/protoc/protoc-gen-authoption/main.go create mode 100644 internal/protoc/protoc-gen-authoption/templates.go create mode 100644 internal/protoc/protoc-gen-authoption/templates/auth_method_mapping.go.tmpl diff --git a/go.mod b/go.mod index 3c67100f96..e38a3449d6 100644 --- a/go.mod +++ b/go.mod @@ -4,20 +4,31 @@ go 1.14 require ( github.com/BurntSushi/toml v0.3.1 + github.com/Masterminds/goutils v1.1.0 // indirect + github.com/Masterminds/semver v1.5.0 // indirect + github.com/Masterminds/sprig v2.22.0+incompatible github.com/caos/logging v0.0.0-20191210002624-b3260f690a6a github.com/ghodss/yaml v1.0.0 + github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b github.com/golang/mock v1.4.3 github.com/golang/protobuf v1.3.5 github.com/google/go-cmp v0.4.0 // indirect + github.com/google/uuid v1.1.1 // indirect github.com/gorilla/schema v1.1.0 github.com/gorilla/securecookie v1.1.1 github.com/grpc-ecosystem/go-grpc-middleware v1.2.0 + github.com/grpc-ecosystem/grpc-gateway v1.14.3 + github.com/huandu/xstrings v1.3.0 // indirect + github.com/imdario/mergo v0.3.8 // indirect github.com/kr/pretty v0.1.0 // indirect + github.com/magiconair/properties v1.8.1 + github.com/mitchellh/copystructure v1.0.0 // indirect github.com/stretchr/testify v1.5.1 golang.org/x/crypto v0.0.0-20200320181102-891825fb96df golang.org/x/net v0.0.0-20200320220750-118fecf932d8 // indirect golang.org/x/sys v0.0.0-20200321134203-328b4cd54aae // indirect golang.org/x/text v0.3.2 // indirect + golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135 google.golang.org/genproto v0.0.0-20200319113533-08878b785e9c // indirect google.golang.org/grpc v1.28.0 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect diff --git a/go.sum b/go.sum index 6e39a2d0fe..8b4fb19b9b 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,13 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg= +github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= +github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60= +github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= +github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q= github.com/caos/logging v0.0.0-20191210002624-b3260f690a6a h1:HOU/3xL/afsZ+2aCstfJlrzRkwYMTFR1TIEgps5ny8s= github.com/caos/logging v0.0.0-20191210002624-b3260f690a6a/go.mod h1:9LKiDE2ChuGv6CHYif/kiugrfEXu9AwDiFWSreX7Wp0= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -19,6 +26,7 @@ github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.4.3 h1:GV+pQPG/EUUbkh47niozDcADz6go/dUwhVzdUQHIVRw= @@ -31,12 +39,20 @@ github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgj github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/schema v1.1.0 h1:CamqUDOFUBqzrvxuz2vEwo8+SUdwsluFh7IlzJh30LY= github.com/gorilla/schema v1.1.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU= github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/grpc-ecosystem/go-grpc-middleware v1.2.0 h1:0IKlLyQ3Hs9nDaiK5cSHAGmcQEIC8l2Ts1u6x5Dfrqg= github.com/grpc-ecosystem/go-grpc-middleware v1.2.0/go.mod h1:mJzapYve32yjrKlk9GbyCZHuPgZsrbyIbyKhSzOpg6s= +github.com/grpc-ecosystem/grpc-gateway v1.14.3 h1:OCJlWkOUoTnl0neNGlf4fUm3TmbEtguw7vR+nGtnDjY= +github.com/grpc-ecosystem/grpc-gateway v1.14.3/go.mod h1:6CwZWGDSPRJidgKAtJVvND6soZe6fT7iteq8wDPdhb0= +github.com/huandu/xstrings v1.3.0 h1:gvV6jG9dTgFEncxo+AF7PH6MZXi/vZl25owA/8Dg8Wo= +github.com/huandu/xstrings v1.3.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ= +github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -48,11 +64,18 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= +github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ= +github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= +github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY= +github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -77,6 +100,7 @@ golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200320220750-118fecf932d8 h1:1+zQlQqEEhUeStBTi653GZAnAuivZq/2hz+Iz+OP7rg= golang.org/x/net v0.0.0-20200320220750-118fecf932d8/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -109,10 +133,12 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= google.golang.org/genproto v0.0.0-20200319113533-08878b785e9c h1:5aI3/f/3eCZps9xwoEnmgfDJDhMbnJpfqeGpjVNgVEI= google.golang.org/genproto v0.0.0-20200319113533-08878b785e9c/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.28.0 h1:bO/TA4OxCOummhSf10siHuG7vJOiwh7SpRpFZDkOgl4= @@ -121,6 +147,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo= gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= diff --git a/internal/protoc/protoc-base/protoc_helper.go b/internal/protoc/protoc-base/protoc_helper.go new file mode 100644 index 0000000000..ac0a210464 --- /dev/null +++ b/internal/protoc/protoc-base/protoc_helper.go @@ -0,0 +1,112 @@ +package protocbase + +import ( + "flag" + "fmt" + "io" + "io/ioutil" + "os" + "strings" + "text/template" + + "github.com/golang/glog" + "github.com/golang/protobuf/proto" + plugin "github.com/golang/protobuf/protoc-gen-go/plugin" + "github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/descriptor" +) + +type GeneratorFunc func(target string, registry *descriptor.Registry, file *descriptor.File) (string, string, error) + +type ProtocGenerator interface { + Generate(target string, registry *descriptor.Registry, file *descriptor.File) (string, string, error) +} + +func (f GeneratorFunc) Generate(target string, registry *descriptor.Registry, file *descriptor.File) (string, string, error) { + return f(target, registry, file) +} + +func parseReq(r io.Reader) (*plugin.CodeGeneratorRequest, error) { + glog.V(1).Info("Parsing code generator request") + + input, err := ioutil.ReadAll(r) + + if err != nil { + glog.Errorf("Failed to read code generator request: %v", err) + return nil, err + } + + req := &plugin.CodeGeneratorRequest{} + + if err = proto.Unmarshal(input, req); err != nil { + glog.Errorf("Failed to unmarshal code generator request: %v", err) + return nil, err + } + + glog.V(1).Info("Parsed code generator request") + + return req, nil +} + +func RunWithBaseTemplate(targetFileNameFmt string, tmpl *template.Template) { + Run(GeneratorFunc(func(target string, registry *descriptor.Registry, file *descriptor.File) (string, string, error) { + fileName := fmt.Sprintf(targetFileNameFmt, strings.Split(target, ".")[0]) + fContent, err := GenerateFromBaseTemplate(tmpl, registry, file) + return fileName, fContent, err + })) +} + +func Run(generator ProtocGenerator) { + flag.Parse() + defer glog.Flush() + + req, err := parseReq(os.Stdin) + if err != nil { + glog.Fatal(err) + } + + registry := descriptor.NewRegistry() + if err = registry.Load(req); err != nil { + glog.Fatal(err) + } + + var result []*plugin.CodeGeneratorResponse_File + + for _, t := range req.FileToGenerate { + file, err := registry.LookupFile(t) + if err != nil { + EmitError(err) + return + } + + fName, fContent, err := generator.Generate(t, registry, file) + if err != nil { + EmitError(err) + return + } + + result = append(result, &plugin.CodeGeneratorResponse_File{ + Name: &fName, + Content: &fContent, + }) + } + + EmitFiles(result) +} + +func EmitFiles(out []*plugin.CodeGeneratorResponse_File) { + EmitResp(&plugin.CodeGeneratorResponse{File: out}) +} + +func EmitError(err error) { + EmitResp(&plugin.CodeGeneratorResponse{Error: proto.String(err.Error())}) +} + +func EmitResp(resp *plugin.CodeGeneratorResponse) { + buf, err := proto.Marshal(resp) + if err != nil { + glog.Fatal(err) + } + if _, err := os.Stdout.Write(buf); err != nil { + glog.Fatal(err) + } +} diff --git a/internal/protoc/protoc-base/templates.go b/internal/protoc/protoc-base/templates.go new file mode 100644 index 0000000000..bb0a627379 --- /dev/null +++ b/internal/protoc/protoc-base/templates.go @@ -0,0 +1,106 @@ +package protocbase + +import ( + "bytes" + "fmt" + "text/template" + "time" + + "github.com/Masterminds/sprig" + "github.com/golang/protobuf/proto" + "github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/descriptor" + "golang.org/x/tools/imports" +) + +var extensions = map[string]*proto.ExtensionDesc{} + +type BaseTemplateData struct { + Now time.Time + File *descriptor.File + + registry *descriptor.Registry +} + +var templateFuncs = map[string]interface{}{ + "option": getOption, +} + +func RegisterTmplFunc(name string, f interface{}) { + if _, existing := templateFuncs[name]; existing { + panic(fmt.Sprintf("func with name %v is already registered", name)) + } + + templateFuncs[name] = f +} + +func RegisterExtension(ext *proto.ExtensionDesc) { + extensions[ext.Name] = ext +} + +func GetBaseTemplateData(registry *descriptor.Registry, file *descriptor.File) *BaseTemplateData { + return &BaseTemplateData{ + Now: time.Now().UTC(), + File: file, + registry: registry, + } +} + +func getOption(opts proto.Message, extName string) interface{} { + extDesc := extensions[extName] + + if !proto.HasExtension(opts, extDesc) { + return nil + } + + ext, err := proto.GetExtension(opts, extDesc) + if err != nil { + panic(err) + } + + return ext +} + +func (data *BaseTemplateData) ResolveMsgType(msgType string) string { + msg, err := data.registry.LookupMsg(data.File.GetPackage(), msgType) + if err != nil { + panic(err) + } + + return msg.GoType(data.File.GoPkg.Path) +} + +func (data *BaseTemplateData) ResolveFile(fileName string) *descriptor.File { + file, err := data.registry.LookupFile(fileName) + if err != nil { + panic(err) + } + + return file +} + +func LoadTemplate(templateData []byte, err error) *template.Template { + if err != nil { + panic(err) + } + + return template.Must(template.New(""). + Funcs(sprig.TxtFuncMap()). + Funcs(templateFuncs). + Parse(string(templateData))) +} + +func GenerateFromTemplate(tmpl *template.Template, data interface{}) (string, error) { + var tpl bytes.Buffer + err := tmpl.Execute(&tpl, data) + if err != nil { + return "", err + } + + tmplResult := tpl.Bytes() + tmplResult, err = imports.Process(".", tmplResult, nil) + return string(tmplResult), err +} + +func GenerateFromBaseTemplate(tmpl *template.Template, registry *descriptor.Registry, file *descriptor.File) (string, error) { + return GenerateFromTemplate(tmpl, GetBaseTemplateData(registry, file)) +} diff --git a/internal/protoc/protoc-gen-authoption/README.md b/internal/protoc/protoc-gen-authoption/README.md new file mode 100644 index 0000000000..2f13790fbd --- /dev/null +++ b/internal/protoc/protoc-gen-authoption/README.md @@ -0,0 +1,37 @@ +# protoc-gen-authoption + +Proto options to annotate auth methods in protos + +## Generate protos/templates +protos: `go generate authoption/generate.go` +templates/install: `go generate generate.go` + +## Usage +``` +// proto file +import "authoption/options.proto"; + +service MyService { + + rpc Hello(Hello) returns (google.protobuf.Empty) { + option (google.api.http) = { + get: "/hello" + }; + + option (caos.zitadel.utils.v1.auth_option) = { + zitadel_permission: "hello.read" + zitadel_check_param: "id" + }; + } + + message Hello { + string id = 1; + } +} +``` +Caos Auth Option is used for granting groups +On each zitadel role is specified which auth methods are allowed to call + +Get protoc-get-authoption: ``go get github.com/caos/zitadel/internal/protoc/protoc-gen-authoption`` + +Protc-Flag: ``--authoption_out=.`` \ No newline at end of file diff --git a/internal/protoc/protoc-gen-authoption/authoption/generate.go b/internal/protoc/protoc-gen-authoption/authoption/generate.go new file mode 100644 index 0000000000..55f6b5dab4 --- /dev/null +++ b/internal/protoc/protoc-gen-authoption/authoption/generate.go @@ -0,0 +1,3 @@ +package authoption + +//go:generate protoc -I. -I$GOPATH/src --go_out=plugins=grpc:$GOPATH/src options.proto diff --git a/internal/protoc/protoc-gen-authoption/authoption/options.pb.go b/internal/protoc/protoc-gen-authoption/authoption/options.pb.go new file mode 100644 index 0000000000..159df24947 --- /dev/null +++ b/internal/protoc/protoc-gen-authoption/authoption/options.pb.go @@ -0,0 +1,105 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: options.proto + +package authoption + +import ( + fmt "fmt" + proto "github.com/golang/protobuf/proto" + descriptor "github.com/golang/protobuf/protoc-gen-go/descriptor" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +type AuthOption struct { + Permission string `protobuf:"bytes,1,opt,name=permission,proto3" json:"permission,omitempty"` + CheckFieldName string `protobuf:"bytes,2,opt,name=check_field_name,json=checkFieldName,proto3" json:"check_field_name,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *AuthOption) Reset() { *m = AuthOption{} } +func (m *AuthOption) String() string { return proto.CompactTextString(m) } +func (*AuthOption) ProtoMessage() {} +func (*AuthOption) Descriptor() ([]byte, []int) { + return fileDescriptor_110d40819f1994f9, []int{0} +} + +func (m *AuthOption) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_AuthOption.Unmarshal(m, b) +} +func (m *AuthOption) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_AuthOption.Marshal(b, m, deterministic) +} +func (m *AuthOption) XXX_Merge(src proto.Message) { + xxx_messageInfo_AuthOption.Merge(m, src) +} +func (m *AuthOption) XXX_Size() int { + return xxx_messageInfo_AuthOption.Size(m) +} +func (m *AuthOption) XXX_DiscardUnknown() { + xxx_messageInfo_AuthOption.DiscardUnknown(m) +} + +var xxx_messageInfo_AuthOption proto.InternalMessageInfo + +func (m *AuthOption) GetPermission() string { + if m != nil { + return m.Permission + } + return "" +} + +func (m *AuthOption) GetCheckFieldName() string { + if m != nil { + return m.CheckFieldName + } + return "" +} + +var E_AuthOption = &proto.ExtensionDesc{ + ExtendedType: (*descriptor.MethodOptions)(nil), + ExtensionType: (*AuthOption)(nil), + Field: 50000, + Name: "caos.zitadel.utils.v1.auth_option", + Tag: "bytes,50000,opt,name=auth_option", + Filename: "options.proto", +} + +func init() { + proto.RegisterType((*AuthOption)(nil), "caos.zitadel.utils.v1.AuthOption") + proto.RegisterExtension(E_AuthOption) +} + +func init() { proto.RegisterFile("options.proto", fileDescriptor_110d40819f1994f9) } + +var fileDescriptor_110d40819f1994f9 = []byte{ + // 252 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x8f, 0x31, 0x4b, 0xc5, 0x30, + 0x14, 0x85, 0x79, 0x0a, 0x82, 0x79, 0x28, 0x52, 0x10, 0x8a, 0x83, 0x54, 0xa7, 0x2e, 0xef, 0x06, + 0x75, 0x73, 0xd3, 0x41, 0x44, 0x50, 0xe1, 0x0d, 0x0e, 0x2e, 0x25, 0x4d, 0xef, 0x6b, 0x83, 0x6d, + 0x6e, 0x49, 0x6e, 0x1c, 0xfc, 0x01, 0xfe, 0x3e, 0x7f, 0x92, 0x34, 0xa9, 0x3e, 0x07, 0xa7, 0x5c, + 0x0e, 0xe7, 0x9c, 0x7c, 0x47, 0x1c, 0xd0, 0xc8, 0x86, 0xac, 0x87, 0xd1, 0x11, 0x53, 0x76, 0xac, + 0x15, 0x79, 0xf8, 0x30, 0xac, 0x1a, 0xec, 0x21, 0xb0, 0xe9, 0x3d, 0xbc, 0x5f, 0x9c, 0x14, 0x2d, + 0x51, 0xdb, 0xa3, 0x8c, 0xa6, 0x3a, 0x6c, 0x64, 0x83, 0x5e, 0x3b, 0x33, 0x32, 0xb9, 0x14, 0x3c, + 0x7f, 0x11, 0xe2, 0x26, 0x70, 0xf7, 0x1c, 0xdb, 0xb2, 0x53, 0x21, 0x46, 0x74, 0x83, 0xf1, 0xde, + 0x90, 0xcd, 0x17, 0xc5, 0xa2, 0xdc, 0x5f, 0xff, 0x51, 0xb2, 0x52, 0x1c, 0xe9, 0x0e, 0xf5, 0x5b, + 0xb5, 0x31, 0xd8, 0x37, 0x95, 0x55, 0x03, 0xe6, 0x3b, 0xd1, 0x75, 0x18, 0xf5, 0xbb, 0x49, 0x7e, + 0x52, 0x03, 0x5e, 0x37, 0x62, 0xa9, 0x02, 0x77, 0x15, 0xcd, 0xc5, 0x90, 0x48, 0xe0, 0x87, 0x04, + 0x1e, 0x91, 0x3b, 0x6a, 0xd2, 0xbf, 0x3e, 0xff, 0xfa, 0xdc, 0x2d, 0x16, 0xe5, 0xf2, 0xf2, 0x0c, + 0xfe, 0x1d, 0x02, 0x5b, 0xc6, 0xb5, 0x50, 0xbf, 0xf7, 0xed, 0xc3, 0xeb, 0x7d, 0x6b, 0xb8, 0x0b, + 0x35, 0x68, 0x1a, 0xe4, 0x14, 0x95, 0x73, 0x54, 0x1a, 0xcb, 0xe8, 0xac, 0xea, 0xd3, 0x76, 0x3d, + 0x3f, 0xab, 0x16, 0xed, 0x6a, 0x2a, 0x48, 0x5c, 0x72, 0x7b, 0xd6, 0x7b, 0xd1, 0x71, 0xf5, 0x1d, + 0x00, 0x00, 0xff, 0xff, 0xd2, 0xa7, 0xf7, 0xca, 0x5a, 0x01, 0x00, 0x00, +} diff --git a/internal/protoc/protoc-gen-authoption/authoption/options.proto b/internal/protoc/protoc-gen-authoption/authoption/options.proto new file mode 100644 index 0000000000..0d86e81073 --- /dev/null +++ b/internal/protoc/protoc-gen-authoption/authoption/options.proto @@ -0,0 +1,17 @@ +syntax = "proto3"; + +package caos.zitadel.utils.v1; + +import "google/protobuf/descriptor.proto"; + +option go_package = "github.com/caos/zitadel/internal/protoc/protoc-gen-authoption/authoption"; + + +extend google.protobuf.MethodOptions { + AuthOption auth_option = 50000; +} + +message AuthOption { + string permission = 1; + string check_field_name = 2; +} \ No newline at end of file diff --git a/internal/protoc/protoc-gen-authoption/generate.go b/internal/protoc/protoc-gen-authoption/generate.go new file mode 100644 index 0000000000..e07d52c3dc --- /dev/null +++ b/internal/protoc/protoc-gen-authoption/generate.go @@ -0,0 +1,4 @@ +package main + +//go:generate go-bindata -pkg main -o templates.go templates +//go:generate go install diff --git a/internal/protoc/protoc-gen-authoption/main.go b/internal/protoc/protoc-gen-authoption/main.go new file mode 100644 index 0000000000..3aba24f52e --- /dev/null +++ b/internal/protoc/protoc-gen-authoption/main.go @@ -0,0 +1,15 @@ +package main + +import ( + base "github.com/caos/zitadel/internal/protoc/protoc-base" + "github.com/caos/zitadel/internal/protoc/protoc-gen-authoption/authoption" +) + +const ( + fileName = "%v.pb.authoptions.go" +) + +func main() { + base.RegisterExtension(authoption.E_AuthOption) + base.RunWithBaseTemplate(fileName, base.LoadTemplate(templatesAuth_method_mappingGoTmplBytes())) +} diff --git a/internal/protoc/protoc-gen-authoption/templates.go b/internal/protoc/protoc-gen-authoption/templates.go new file mode 100644 index 0000000000..9daad6521c --- /dev/null +++ b/internal/protoc/protoc-gen-authoption/templates.go @@ -0,0 +1,237 @@ +// Code generated by go-bindata. +// sources: +// templates/auth_method_mapping.go.tmpl +// DO NOT EDIT! + +package main + +import ( + "bytes" + "compress/gzip" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "strings" + "time" +) + +func bindataRead(data []byte, name string) ([]byte, error) { + gz, err := gzip.NewReader(bytes.NewBuffer(data)) + if err != nil { + return nil, fmt.Errorf("Read %q: %v", name, err) + } + + var buf bytes.Buffer + _, err = io.Copy(&buf, gz) + clErr := gz.Close() + + if err != nil { + return nil, fmt.Errorf("Read %q: %v", name, err) + } + if clErr != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +type asset struct { + bytes []byte + info os.FileInfo +} + +type bindataFileInfo struct { + name string + size int64 + mode os.FileMode + modTime time.Time +} + +func (fi bindataFileInfo) Name() string { + return fi.name +} +func (fi bindataFileInfo) Size() int64 { + return fi.size +} +func (fi bindataFileInfo) Mode() os.FileMode { + return fi.mode +} +func (fi bindataFileInfo) ModTime() time.Time { + return fi.modTime +} +func (fi bindataFileInfo) IsDir() bool { + return false +} +func (fi bindataFileInfo) Sys() interface{} { + return nil +} + +var _templatesAuth_method_mappingGoTmpl = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x8c\x52\xc1\x6a\xe3\x30\x10\x3d\xaf\xbe\x62\x30\x3e\xb4\x21\x95\xd8\x6b\xa0\x87\x25\xdd\x2e\x3d\xb4\x09\x6c\x76\xaf\x41\xb5\x27\xb2\x88\x2d\x19\x49\x0e\xb4\x42\xff\xbe\x8c\xed\xac\x9d\xb4\x0b\xeb\x93\xac\x99\x37\xef\xbd\xd1\x13\x02\xd6\xb6\x44\x50\x68\xd0\xc9\x80\x25\xbc\xbe\x41\xeb\x6c\xb0\xc5\x9d\x42\x73\x27\xbb\x50\x35\x18\x2a\x5b\x72\x78\xd8\xc0\xcb\x66\x07\xdf\x1f\x9e\x76\x9c\xb1\x56\x16\x47\xa9\x10\x62\xe4\x8f\xba\x46\xfe\xc3\x6e\x8f\x8a\xbf\xc8\x06\x53\x62\x8c\xe9\xa6\xb5\x2e\xc0\x0d\x03\x00\xc8\x94\xb5\xaa\x46\xae\x6c\x2d\x8d\xe2\xd6\x29\xa1\x5c\x5b\x64\x7d\x91\x7d\xe9\x82\xae\xfd\x9e\xa8\x20\x53\x3a\x54\xdd\x2b\x2f\x6c\x23\x0a\x69\xbd\x78\xd7\x41\x96\x58\x0b\x6d\x02\x3a\x23\x6b\x41\x6d\xd9\x19\x43\x53\xfe\x03\x33\x90\xdd\x32\x16\x23\x38\x69\x14\x42\xee\x61\x75\x0f\x83\xf2\x9f\xe8\x4e\xba\x40\x0f\x24\x5c\x2c\x16\x0c\x16\x10\x63\xee\xcf\x66\x60\x21\x18\x3b\x49\x37\xbf\xdc\x7f\xeb\x42\xf5\xdc\x2f\xc6\xc3\x3d\x4c\x0e\xf8\x54\x78\x96\x6d\xab\x8d\x82\xd8\xdb\x9c\xa8\x1b\xa2\xce\x3d\x1f\xba\x88\x60\xfc\x62\x84\xbc\x21\xfc\xa6\x0d\xd4\x63\xdb\xa0\xad\x81\xbc\xe1\x9b\xfe\xe4\x21\x23\x7f\x7c\xf4\xc7\x7b\x56\x7e\xfa\xca\x89\x78\x3f\x74\x67\x70\x39\x50\x1f\x40\x9a\x72\x36\xf7\xef\x89\x6f\xd1\x35\xda\x7b\xa2\x98\x61\xfa\xf7\x12\x31\xe6\xc3\x72\xb6\xc3\x33\xa7\xc4\x67\xee\x45\x8c\xe3\x29\x5b\x5d\x7b\x1f\xa4\xc6\x8b\x79\xf4\x4d\x6c\x2b\xc8\x62\xfc\x4c\x46\x4a\xd9\xf2\x03\x6e\x5d\x61\x71\xdc\x4a\x27\x9b\x2b\x5c\x5f\x78\xd4\x58\x97\xa3\x94\x4b\x6c\x5a\xce\xd6\x80\xe6\xbc\xe7\x18\x61\xf8\x49\x8c\x1d\x3a\x53\x7c\x78\x54\xeb\xf4\xbb\x24\x0b\xfb\x27\x8a\x4f\x81\x6d\xb0\xee\xe6\x84\x4e\x1f\x34\xba\xb9\xdb\x9d\x3d\xa2\xf9\x3d\x16\x96\x40\x77\x6b\x6b\x0e\xb0\xb8\xda\x08\x5d\x6a\x75\x0b\x94\x42\xfe\xcb\x48\xf7\x46\x89\x43\x37\x9b\x3f\x66\xc4\x61\xe8\x9c\x81\x29\xdb\xfc\x42\xd1\x67\x82\x26\xde\xe5\xbf\xf2\x79\x4b\x5e\x07\xdf\x90\xd2\x9f\x00\x00\x00\xff\xff\xbf\x91\xbb\x3b\xf2\x03\x00\x00") + +func templatesAuth_method_mappingGoTmplBytes() ([]byte, error) { + return bindataRead( + _templatesAuth_method_mappingGoTmpl, + "templates/auth_method_mapping.go.tmpl", + ) +} + +func templatesAuth_method_mappingGoTmpl() (*asset, error) { + bytes, err := templatesAuth_method_mappingGoTmplBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "templates/auth_method_mapping.go.tmpl", size: 1010, mode: os.FileMode(420), modTime: time.Unix(1584960713, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +// Asset loads and returns the asset for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func Asset(name string) ([]byte, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) + } + return a.bytes, nil + } + return nil, fmt.Errorf("Asset %s not found", name) +} + +// MustAsset is like Asset but panics when Asset would return an error. +// It simplifies safe initialization of global variables. +func MustAsset(name string) []byte { + a, err := Asset(name) + if err != nil { + panic("asset: Asset(" + name + "): " + err.Error()) + } + + return a +} + +// AssetInfo loads and returns the asset info for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func AssetInfo(name string) (os.FileInfo, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) + } + return a.info, nil + } + return nil, fmt.Errorf("AssetInfo %s not found", name) +} + +// AssetNames returns the names of the assets. +func AssetNames() []string { + names := make([]string, 0, len(_bindata)) + for name := range _bindata { + names = append(names, name) + } + return names +} + +// _bindata is a table, holding each asset generator, mapped to its name. +var _bindata = map[string]func() (*asset, error){ + "templates/auth_method_mapping.go.tmpl": templatesAuth_method_mappingGoTmpl, +} + +// AssetDir returns the file names below a certain +// directory embedded in the file by go-bindata. +// For example if you run go-bindata on data/... and data contains the +// following hierarchy: +// data/ +// foo.txt +// img/ +// a.png +// b.png +// then AssetDir("data") would return []string{"foo.txt", "img"} +// AssetDir("data/img") would return []string{"a.png", "b.png"} +// AssetDir("foo.txt") and AssetDir("notexist") would return an error +// AssetDir("") will return []string{"data"}. +func AssetDir(name string) ([]string, error) { + node := _bintree + if len(name) != 0 { + cannonicalName := strings.Replace(name, "\\", "/", -1) + pathList := strings.Split(cannonicalName, "/") + for _, p := range pathList { + node = node.Children[p] + if node == nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + } + } + if node.Func != nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + rv := make([]string, 0, len(node.Children)) + for childName := range node.Children { + rv = append(rv, childName) + } + return rv, nil +} + +type bintree struct { + Func func() (*asset, error) + Children map[string]*bintree +} + +var _bintree = &bintree{nil, map[string]*bintree{ + "templates": &bintree{nil, map[string]*bintree{ + "auth_method_mapping.go.tmpl": &bintree{templatesAuth_method_mappingGoTmpl, map[string]*bintree{}}, + }}, +}} + +// RestoreAsset restores an asset under the given directory +func RestoreAsset(dir, name string) error { + data, err := Asset(name) + if err != nil { + return err + } + info, err := AssetInfo(name) + if err != nil { + return err + } + err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) + if err != nil { + return err + } + err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) + if err != nil { + return err + } + err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) + if err != nil { + return err + } + return nil +} + +// RestoreAssets restores an asset under the given directory recursively +func RestoreAssets(dir, name string) error { + children, err := AssetDir(name) + // File + if err != nil { + return RestoreAsset(dir, name) + } + // Dir + for _, child := range children { + err = RestoreAssets(dir, filepath.Join(name, child)) + if err != nil { + return err + } + } + return nil +} + +func _filePath(dir, name string) string { + cannonicalName := strings.Replace(name, "\\", "/", -1) + return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) +} diff --git a/internal/protoc/protoc-gen-authoption/templates/auth_method_mapping.go.tmpl b/internal/protoc/protoc-gen-authoption/templates/auth_method_mapping.go.tmpl new file mode 100644 index 0000000000..031dae21ee --- /dev/null +++ b/internal/protoc/protoc-gen-authoption/templates/auth_method_mapping.go.tmpl @@ -0,0 +1,35 @@ +// Code generated by protoc-gen-authmethod. DO NOT EDIT. + +package {{.File.GoPkg.Name}} + + +import ( + "google.golang.org/grpc" + + utils_auth "github.com/caos/zitadel/internal/auth" + utils_grpc "github.com/caos/zitadel/internal/grpc" +) + +{{ range $s := .File.Services }} + +/** + * {{$s.Name}} + */ + +var {{$s.Name}}_AuthMethods = utils_auth.AuthMethodMapping { + {{ range $m := $s.Method}} + {{ $mAuthOpt := option $m.Options "caos.zitadel.utils.v1.auth_option" }} + {{ if and $mAuthOpt $mAuthOpt.Permission }} + "/{{$.File.Package}}.{{$s.Name}}/{{.Name}}": utils_auth.AuthOption{ + Permission: "{{$mAuthOpt.Permission}}", + CheckParam: "{{$mAuthOpt.CheckFieldName}}", + }, + {{end}} + {{ end}} +} + +func {{$s.Name}}_Authorization_Interceptor(verifier utils_auth.TokenVerifier, authConf *utils_auth.AuthConfig) grpc.UnaryServerInterceptor { + return utils_grpc.AuthorizationInterceptor(verifier, authConf, {{$s.Name}}_AuthMethods) +} + +{{ end }} \ No newline at end of file From 5843bac5f921102d24c8f5e80f229b02cd3e2d95 Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Mon, 23 Mar 2020 13:26:05 +0100 Subject: [PATCH 13/39] ad i18n and renderer and move headers --- go.mod | 7 +- go.sum | 12 ++- internal/api/grpc/auth_interceptor.go | 3 +- internal/api/grpc/header.go | 8 +- internal/api/header.go | 8 ++ internal/api/html/i18n.go | 108 ++++++++++++++++++++++++++ internal/api/html/renderer.go | 82 +++++++++++++++++++ 7 files changed, 213 insertions(+), 15 deletions(-) create mode 100644 internal/api/header.go create mode 100644 internal/api/html/i18n.go create mode 100644 internal/api/html/renderer.go diff --git a/go.mod b/go.mod index e38a3449d6..f3882f1414 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,6 @@ require ( github.com/Masterminds/semver v1.5.0 // indirect github.com/Masterminds/sprig v2.22.0+incompatible github.com/caos/logging v0.0.0-20191210002624-b3260f690a6a - github.com/ghodss/yaml v1.0.0 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b github.com/golang/mock v1.4.3 github.com/golang/protobuf v1.3.5 @@ -21,16 +20,16 @@ require ( github.com/huandu/xstrings v1.3.0 // indirect github.com/imdario/mergo v0.3.8 // indirect github.com/kr/pretty v0.1.0 // indirect - github.com/magiconair/properties v1.8.1 github.com/mitchellh/copystructure v1.0.0 // indirect + github.com/nicksnyder/go-i18n/v2 v2.0.3 github.com/stretchr/testify v1.5.1 golang.org/x/crypto v0.0.0-20200320181102-891825fb96df golang.org/x/net v0.0.0-20200320220750-118fecf932d8 // indirect golang.org/x/sys v0.0.0-20200321134203-328b4cd54aae // indirect - golang.org/x/text v0.3.2 // indirect + golang.org/x/text v0.3.2 golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135 google.golang.org/genproto v0.0.0-20200319113533-08878b785e9c // indirect google.golang.org/grpc v1.28.0 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect - gopkg.in/yaml.v2 v2.2.8 // indirect + gopkg.in/yaml.v2 v2.2.7 ) diff --git a/go.sum b/go.sum index 8b4fb19b9b..e5db0f7feb 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,5 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.0/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg= @@ -64,12 +65,12 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/nicksnyder/go-i18n/v2 v2.0.3 h1:ks/JkQiOEhhuF6jpNvx+Wih1NIiXzUnZeZVnJuI8R8M= +github.com/nicksnyder/go-i18n/v2 v2.0.3/go.mod h1:oDab7q8XCYMRlcrBnaY/7B1eOectbvj6B1UPBT+p5jo= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -89,6 +90,7 @@ go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190506204251-e1dfcc566284/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200320181102-891825fb96df h1:lDWgvUvNnaTnNBc/dwOty86cFeKoKWbwy2wQj0gIxbU= golang.org/x/crypto v0.0.0-20200320181102-891825fb96df/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -100,6 +102,7 @@ golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200320220750-118fecf932d8 h1:1+zQlQqEEhUeStBTi653GZAnAuivZq/2hz+Iz+OP7rg= golang.org/x/net v0.0.0-20200320220750-118fecf932d8/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -111,6 +114,7 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191206220618-eeba5f6aabab h1:FvshnhkKW+LO3HWHodML8kuVX8rnJTxKm9dFPuI68UM= golang.org/x/sys v0.0.0-20191206220618-eeba5f6aabab/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200321134203-328b4cd54aae h1:3tcmuaB7wwSZtelmiv479UjUB+vviwABz7a133ZwOKQ= @@ -125,6 +129,7 @@ golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135 h1:5Beo0mZN8dRzgrMMkDp0jc8YXQKx9DiJ2k1dkvGsn5A= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= @@ -146,12 +151,11 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo= gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= rsc.io/quote/v3 v3.1.0 h1:9JKUTTIUgS6kzR9mK1YuGKv6Nl+DijDNIc0ghT58FaY= diff --git a/internal/api/grpc/auth_interceptor.go b/internal/api/grpc/auth_interceptor.go index 4e91d11714..6ade793b1e 100644 --- a/internal/api/grpc/auth_interceptor.go +++ b/internal/api/grpc/auth_interceptor.go @@ -7,6 +7,7 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "github.com/caos/zitadel/internal/api" "github.com/caos/zitadel/internal/api/auth" ) @@ -22,7 +23,7 @@ func AuthorizationInterceptor(verifier auth.TokenVerifier, authConfig *auth.Conf return nil, status.Error(codes.Unauthenticated, "auth header missing") } - orgID := GetHeader(ctx, ZitadelOrgID) + orgID := GetHeader(ctx, api.ZitadelOrgID) ctx, err := auth.CheckUserAuthorization(ctx, req, authToken, orgID, verifier, authConfig, authOpt) if err != nil { diff --git a/internal/api/grpc/header.go b/internal/api/grpc/header.go index 5d217b7518..f1498c1562 100644 --- a/internal/api/grpc/header.go +++ b/internal/api/grpc/header.go @@ -4,12 +4,8 @@ import ( "context" "github.com/grpc-ecosystem/go-grpc-middleware/util/metautils" -) -const ( - Authorization = "authorization" - - ZitadelOrgID = "x-zitadel-orgid" + "github.com/caos/zitadel/internal/api" ) func GetHeader(ctx context.Context, headername string) string { @@ -17,5 +13,5 @@ func GetHeader(ctx context.Context, headername string) string { } func GetAuthorizationHeader(ctx context.Context) string { - return GetHeader(ctx, Authorization) + return GetHeader(ctx, api.Authorization) } diff --git a/internal/api/header.go b/internal/api/header.go new file mode 100644 index 0000000000..fa8efc0282 --- /dev/null +++ b/internal/api/header.go @@ -0,0 +1,8 @@ +package api + +const ( + Authorization = "authorization" + AcceptLanguage = "Accept-Language" + + ZitadelOrgID = "x-zitadel-orgid" +) diff --git a/internal/api/html/i18n.go b/internal/api/html/i18n.go new file mode 100644 index 0000000000..dd5d272668 --- /dev/null +++ b/internal/api/html/i18n.go @@ -0,0 +1,108 @@ +package html + +import ( + "encoding/json" + "io/ioutil" + "net/http" + "path" + + "github.com/BurntSushi/toml" + "github.com/caos/logging" + "github.com/nicksnyder/go-i18n/v2/i18n" + "golang.org/x/text/language" + "gopkg.in/yaml.v2" + + "github.com/caos/zitadel/internal/api" + http_util "github.com/caos/zitadel/internal/api/http" + "github.com/caos/zitadel/internal/errors" +) + +type Translator struct { + bundle *i18n.Bundle + cookieName string + cookieHandler *http_util.CookieHandler +} + +type TranslatorConfig struct { + Path string + DefaultLanguage language.Tag + CookieName string +} + +func NewTranslator(config TranslatorConfig) (*Translator, error) { + t := new(Translator) + var err error + t.bundle, err = newBundle(config.Path, config.DefaultLanguage) + if err != nil { + return nil, err + } + t.cookieHandler = http_util.NewCookieHandler() + t.cookieName = config.CookieName + return t, nil +} + +func newBundle(i18nDir string, defaultLanguage language.Tag) (*i18n.Bundle, error) { + bundle := i18n.NewBundle(defaultLanguage) + bundle.RegisterUnmarshalFunc("yaml", yaml.Unmarshal) + bundle.RegisterUnmarshalFunc("yml", yaml.Unmarshal) + bundle.RegisterUnmarshalFunc("json", json.Unmarshal) + bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal) + files, err := ioutil.ReadDir(i18nDir) + if err != nil { + return nil, errors.ThrowNotFound(err, "HTML-MnXRie", "path not found") + } + for _, file := range files { + bundle.MustLoadMessageFile(path.Join(i18nDir, file.Name())) + } + return bundle, nil +} + +func (t *Translator) LocalizeFromRequest(r *http.Request, id string, args map[string]interface{}) string { + s, err := t.localizerFromRequest(r).Localize(&i18n.LocalizeConfig{ + MessageID: id, + TemplateData: args, + }) + if err != nil { + logging.Log("HTML-MsF5sx").WithError(err).Warnf("missing translation") + return id + } + return s +} + +func (t *Translator) Localize(id string, args map[string]interface{}) string { + s, _ := t.localizer().Localize(&i18n.LocalizeConfig{ + MessageID: id, + TemplateData: args, + }) + return s +} + +func (t *Translator) Lang(r *http.Request) language.Tag { + matcher := language.NewMatcher(t.bundle.LanguageTags()) + tag, _ := language.MatchStrings(matcher, t.langsFromRequest(r)...) + return tag +} + +func (t *Translator) SetLangCookie(w http.ResponseWriter, lang language.Tag) { + t.cookieHandler.SetCookie(w, t.cookieName, lang.String()) +} + +func (t *Translator) localizerFromRequest(r *http.Request) *i18n.Localizer { + return t.localizer(t.langsFromRequest(r)...) +} + +func (t *Translator) localizer(langs ...string) *i18n.Localizer { + return i18n.NewLocalizer(t.bundle, langs...) +} + +func (t *Translator) langsFromRequest(r *http.Request) []string { + langs := make([]string, 0) + if r != nil { + lang, err := t.cookieHandler.GetCookieValue(r, t.cookieName) + if err == nil { + langs = append(langs, lang) + } + langs = append(langs, r.Header.Get(api.AcceptLanguage)) + } + return langs +} diff --git a/internal/api/html/renderer.go b/internal/api/html/renderer.go new file mode 100644 index 0000000000..182087e31d --- /dev/null +++ b/internal/api/html/renderer.go @@ -0,0 +1,82 @@ +package html + +import ( + "net/http" + "path" + "text/template" + + "github.com/caos/logging" + "golang.org/x/text/language" +) + +const ( + TranslateFn = "t" +) + +type Renderer struct { + Templates map[string]*template.Template + i18n *Translator +} + +func NewRenderer(templatesDir string, tmplMapping map[string]string, funcs map[string]interface{}, translatorConfig TranslatorConfig) (*Renderer, error) { + var err error + r := new(Renderer) + r.i18n, err = NewTranslator(translatorConfig) + if err != nil { + return nil, err + } + r.loadTemplates(templatesDir, tmplMapping, funcs) + return r, nil +} + +func (r *Renderer) RenderTemplate(w http.ResponseWriter, req *http.Request, tmpl *template.Template, data interface{}, reqFuncs map[string]interface{}) { + reqFuncs = r.registerTranslateFn(req, reqFuncs) + if err := tmpl.Funcs(reqFuncs).Execute(w, data); err != nil { + logging.Log("HTML-lF8F6w").WithError(err).WithField("template", tmpl.Name).Error("error rendering template") + } +} + +func (r *Renderer) Localize(id string, args map[string]interface{}) string { + return r.i18n.Localize(id, args) +} + +func (r *Renderer) LocalizeFromRequest(req *http.Request, id string, args map[string]interface{}) string { + return r.i18n.LocalizeFromRequest(req, id, args) +} +func (r *Renderer) Lang(req *http.Request) language.Tag { + return r.i18n.Lang(req) +} + +func (r *Renderer) loadTemplates(templatesDir string, tmplMapping map[string]string, funcs map[string]interface{}) { + funcs = r.registerTranslateFn(nil, funcs) + funcs[TranslateFn] = func(id string, args ...interface{}) string { + return id + } + tmpls := template.Must(template.New("").Funcs(funcs).ParseGlob(path.Join(templatesDir, "*.html"))) + r.Templates = make(map[string]*template.Template, len(tmplMapping)) + for name, file := range tmplMapping { + r.Templates[name] = tmpls.Lookup(file) + } +} + +func (r *Renderer) registerTranslateFn(req *http.Request, funcs map[string]interface{}) map[string]interface{} { + if funcs == nil { + funcs = make(map[string]interface{}) + } + funcs[TranslateFn] = func(id string, args ...interface{}) string { + m := map[string]interface{}{} + var key string + for i, arg := range args { + if i%2 == 0 { + key = arg.(string) + continue + } + m[key] = arg + } + if r == nil { + return r.Localize(id, m) + } + return r.LocalizeFromRequest(req, id, m) + } + return funcs +} From ecb894258f8edf7bd914deb7071040651b4c2246 Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Mon, 23 Mar 2020 14:25:01 +0100 Subject: [PATCH 14/39] remove eventstore flag from cmd --- cmd/zitadel/main.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/cmd/zitadel/main.go b/cmd/zitadel/main.go index 24f3f57abd..f44be202ab 100644 --- a/cmd/zitadel/main.go +++ b/cmd/zitadel/main.go @@ -22,7 +22,6 @@ type Config struct { func main() { configPath := flag.String("config-file", "/zitadel/config/startup.yaml", "path to the config file") - eventstoreEnabled := flag.Bool("eventstore", true, "enable eventstore") managementEnabled := flag.Bool("management", true, "enable management api") authEnabled := flag.Bool("auth", true, "enable auth api") adminEnabled := flag.Bool("admin", true, "enable admin api") @@ -34,10 +33,6 @@ func main() { logging.Log("MAIN-FaF2r").OnError(err).Fatal("cannot read config") ctx := context.Background() - if *eventstoreEnabled { - err = eventstore.Start(ctx, conf.Eventstore) - logging.Log("MAIN-sj2Sd").OnError(err).Fatal("error starting eventstore") - } if *managementEnabled { err = management.Start(ctx, conf.Management) logging.Log("MAIN-39Nv5").OnError(err).Fatal("error starting management api") From 6deb0b029a6a07cdb6ddea0c8cb20c9a3fb82457 Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Mon, 23 Mar 2020 16:31:26 +0100 Subject: [PATCH 15/39] add tests for config --- internal/config/config.go | 32 +--- internal/config/config_test.go | 198 +++++++++++++++++++++ internal/config/testdata/invalid.json | 3 + internal/config/testdata/non_parsable.json | 1 + internal/config/testdata/valid.json | 3 + 5 files changed, 214 insertions(+), 23 deletions(-) create mode 100644 internal/config/config_test.go create mode 100644 internal/config/testdata/invalid.json create mode 100644 internal/config/testdata/non_parsable.json create mode 100644 internal/config/testdata/valid.json diff --git a/internal/config/config.go b/internal/config/config.go index 5c524e1525..5740cd5f1d 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -7,31 +7,21 @@ import ( "path/filepath" "github.com/BurntSushi/toml" - "github.com/ghodss/yaml" + "gopkg.in/yaml.v2" "github.com/caos/zitadel/internal/errors" ) -type Reader interface { - Unmarshal(data []byte, o interface{}) error -} - type ValidatableConfiguration interface { Validate() error } type ReaderFunc func(data []byte, o interface{}) error -func (c ReaderFunc) Unmarshal(data []byte, o interface{}) error { - return c(data, o) -} - var ( - JSONReader = ReaderFunc(json.Unmarshal) - TOMLReader = ReaderFunc(toml.Unmarshal) - YAMLReader = ReaderFunc(func(y []byte, o interface{}) error { - return yaml.Unmarshal(y, o) - }) + JSONReader = json.Unmarshal + TOMLReader = toml.Unmarshal + YAMLReader = yaml.Unmarshal ) // Read deserializes each config file to the target obj @@ -39,11 +29,11 @@ var ( // env vars are replaced in the config file as well as the file path func Read(obj interface{}, configFiles ...string) error { for _, cf := range configFiles { - configReader, err := configReaderForFile(cf) + readerFunc, err := readerFuncForFile(cf) if err != nil { return err } - if err := readConfigFile(configReader, cf, obj); err != nil { + if err := readConfigFile(readerFunc, cf, obj); err != nil { return err } } @@ -57,13 +47,9 @@ func Read(obj interface{}, configFiles ...string) error { return nil } -func readConfigFile(configReader Reader, configFile string, obj interface{}) error { +func readConfigFile(readerFunc ReaderFunc, configFile string, obj interface{}) error { configFile = os.ExpandEnv(configFile) - if _, err := os.Stat(configFile); err != nil { - return errors.ThrowNotFoundf(err, "CONFI-Hs93M", "config file %s does not exist", configFile) - } - configStr, err := ioutil.ReadFile(configFile) if err != nil { return errors.ThrowInternalf(err, "CONFI-nJk2a", "failed to read config file %s", configFile) @@ -71,14 +57,14 @@ func readConfigFile(configReader Reader, configFile string, obj interface{}) err configStr = []byte(os.ExpandEnv(string(configStr))) - if err := configReader.Unmarshal(configStr, obj); err != nil { + if err := readerFunc(configStr, obj); err != nil { return errors.ThrowInternalf(err, "CONFI-2Mc3c", "error parse config file %s", configFile) } return nil } -func configReaderForFile(configFile string) (Reader, error) { +func readerFuncForFile(configFile string) (ReaderFunc, error) { ext := filepath.Ext(configFile) switch ext { case ".yaml", ".yml": diff --git a/internal/config/config_test.go b/internal/config/config_test.go new file mode 100644 index 0000000000..ba517b6061 --- /dev/null +++ b/internal/config/config_test.go @@ -0,0 +1,198 @@ +package config + +import ( + "errors" + "reflect" + "runtime" + "testing" + + "github.com/stretchr/testify/assert" +) + +type test struct { + Test bool +} + +type validatable struct { + Test bool +} + +func (v *validatable) Validate() error { + if v.Test { + return nil + } + return errors.New("invalid") +} + +func TestRead(t *testing.T) { + type args struct { + obj interface{} + configFiles []string + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + "not supoorted config file error", + args{ + configFiles: []string{"notsupported.unknown"}, + obj: nil, + }, + true, + }, + { + "non existing config file error", + args{ + configFiles: []string{"nonexisting.yaml"}, + obj: nil, + }, + true, + }, + { + "non parsable config file error", + args{ + configFiles: []string{"./testdata/non_parsable.json"}, + obj: &test{}, + }, + true, + }, + { + "invalid parsable config file error", + args{ + configFiles: []string{"./testdata/invalid.json"}, + obj: &validatable{}, + }, + true, + }, + { + "parsable config file ok", + args{ + configFiles: []string{"./testdata/valid.json"}, + obj: &test{}, + }, + false, + }, + { + "valid parsable config file ok", + args{ + configFiles: []string{"./testdata/valid.json"}, + obj: &validatable{}, + }, + false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := Read(tt.args.obj, tt.args.configFiles...); (err != nil) != tt.wantErr { + t.Errorf("Read() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func Test_readerFuncForFile(t *testing.T) { + type args struct { + configFile string + } + tests := []struct { + name string + args args + want ReaderFunc + wantErr bool + }{ + { + "unknown extension error", + args{configFile: "test.unknown"}, + nil, + true, + }, + { + "toml", + args{configFile: "test.toml"}, + TOMLReader, + false, + }, + { + "json", + args{configFile: "test.json"}, + JSONReader, + false, + }, + { + "yaml", + args{configFile: "test.yaml"}, + YAMLReader, + false, + }, + { + "yml", + args{configFile: "test.yml"}, + YAMLReader, + false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := readerFuncForFile(tt.args.configFile) + if (err != nil) != tt.wantErr { + t.Errorf("configReaderForFile() error = %v, wantErr %v", err, tt.wantErr) + return + } + funcName1 := runtime.FuncForPC(reflect.ValueOf(got).Pointer()).Name() + funcName2 := runtime.FuncForPC(reflect.ValueOf(tt.want).Pointer()).Name() + if !assert.Equal(t, funcName1, funcName2) { + t.Errorf("configReaderForFile() got = %v, want %v", funcName1, funcName2) + } + }) + } +} + +func Test_readConfigFile(t *testing.T) { + type args struct { + configReader ReaderFunc + configFile string + obj interface{} + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + "non existing config file error", + args{ + configReader: YAMLReader, + configFile: "nonexisting.json", + obj: nil, + }, + true, + }, + { + "non parsable config file error", + args{ + configReader: YAMLReader, + configFile: "./testdata/non_parsable.json", + obj: &test{}, + }, + true, + }, + { + "parsable config file no error", + args{ + configReader: YAMLReader, + configFile: "./testdata/valid.json", + obj: &test{}, + }, + false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := readConfigFile(tt.args.configReader, tt.args.configFile, tt.args.obj); (err != nil) != tt.wantErr { + t.Errorf("readConfigFile() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/config/testdata/invalid.json b/internal/config/testdata/invalid.json new file mode 100644 index 0000000000..454b39367e --- /dev/null +++ b/internal/config/testdata/invalid.json @@ -0,0 +1,3 @@ +{ + "Test" : false +} \ No newline at end of file diff --git a/internal/config/testdata/non_parsable.json b/internal/config/testdata/non_parsable.json new file mode 100644 index 0000000000..8318c86b35 --- /dev/null +++ b/internal/config/testdata/non_parsable.json @@ -0,0 +1 @@ +Test \ No newline at end of file diff --git a/internal/config/testdata/valid.json b/internal/config/testdata/valid.json new file mode 100644 index 0000000000..65f3700045 --- /dev/null +++ b/internal/config/testdata/valid.json @@ -0,0 +1,3 @@ +{ + "Test" : true +} \ No newline at end of file From a5ca611dccc51086b6c0b78640a3e5b1ca13f4aa Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Tue, 24 Mar 2020 07:22:31 +0100 Subject: [PATCH 16/39] fix path in error_creator.go message --- internal/errors/generate/error_creator.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/errors/generate/error_creator.go b/internal/errors/generate/error_creator.go index 02a5538136..52139196a1 100644 --- a/internal/errors/generate/error_creator.go +++ b/internal/errors/generate/error_creator.go @@ -32,7 +32,7 @@ func main() { fmt.Print(` !!!!! - Add status mapping in grpc/errors/caos_errors.go + Add status mapping in internal/api/grpc/caos_errors.go !!!!!`) } From 96b88f5d8cb87cb751d224eec875ba9261bd054c Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Tue, 24 Mar 2020 14:15:01 +0100 Subject: [PATCH 17/39] add tracing and refactor some api pkgs --- go.mod | 13 +- go.sum | 180 ++++++++++++++++++ .../api/grpc/client/middleware/tracing.go | 38 ++++ internal/api/grpc/server/gateway.go | 110 +++++++++++ .../middleware}/auth_interceptor.go | 7 +- .../middleware}/error_interceptor.go | 6 +- .../api/grpc/server/middleware/tracing.go | 33 ++++ internal/api/grpc/{ => server}/probes.go | 2 +- internal/api/grpc/server/server.go | 53 ++++++ internal/api/header.go | 6 +- internal/api/http/listener.go | 21 ++ .../api/http/middleware/cors_interceptor.go | 47 +++++ .../api/http/middleware/trace_interceptor.go | 12 ++ internal/api/probes.go | 11 ++ internal/tracing/caller.go | 24 +++ internal/tracing/config/config.go | 61 ++++++ internal/tracing/generate.go | 3 + internal/tracing/google/config.go | 25 +++ internal/tracing/google/googletracing.go | 95 +++++++++ internal/tracing/http_handler.go | 30 +++ internal/tracing/log/config.go | 21 ++ internal/tracing/log/logTracing.go | 74 +++++++ internal/tracing/mock/tracing_mock.go | 155 +++++++++++++++ internal/tracing/mock/tracing_mock_impl.go | 20 ++ internal/tracing/span.go | 89 +++++++++ internal/tracing/tracing.go | 74 +++++++ 26 files changed, 1198 insertions(+), 12 deletions(-) create mode 100644 internal/api/grpc/client/middleware/tracing.go create mode 100644 internal/api/grpc/server/gateway.go rename internal/api/grpc/{ => server/middleware}/auth_interceptor.go (84%) rename internal/api/grpc/{ => server/middleware}/error_interceptor.go (74%) create mode 100644 internal/api/grpc/server/middleware/tracing.go rename internal/api/grpc/{ => server}/probes.go (98%) create mode 100644 internal/api/grpc/server/server.go create mode 100644 internal/api/http/listener.go create mode 100644 internal/api/http/middleware/cors_interceptor.go create mode 100644 internal/api/http/middleware/trace_interceptor.go create mode 100644 internal/api/probes.go create mode 100644 internal/tracing/caller.go create mode 100644 internal/tracing/config/config.go create mode 100644 internal/tracing/generate.go create mode 100644 internal/tracing/google/config.go create mode 100644 internal/tracing/google/googletracing.go create mode 100644 internal/tracing/http_handler.go create mode 100644 internal/tracing/log/config.go create mode 100644 internal/tracing/log/logTracing.go create mode 100644 internal/tracing/mock/tracing_mock.go create mode 100644 internal/tracing/mock/tracing_mock_impl.go create mode 100644 internal/tracing/span.go create mode 100644 internal/tracing/tracing.go diff --git a/go.mod b/go.mod index f3882f1414..34c29cbd49 100644 --- a/go.mod +++ b/go.mod @@ -3,15 +3,17 @@ module github.com/caos/zitadel go 1.14 require ( + cloud.google.com/go v0.53.0 // indirect + contrib.go.opencensus.io/exporter/stackdriver v0.13.0 github.com/BurntSushi/toml v0.3.1 github.com/Masterminds/goutils v1.1.0 // indirect github.com/Masterminds/semver v1.5.0 // indirect github.com/Masterminds/sprig v2.22.0+incompatible + github.com/aws/aws-sdk-go v1.29.16 // indirect github.com/caos/logging v0.0.0-20191210002624-b3260f690a6a github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b github.com/golang/mock v1.4.3 github.com/golang/protobuf v1.3.5 - github.com/google/go-cmp v0.4.0 // indirect github.com/google/uuid v1.1.1 // indirect github.com/gorilla/schema v1.1.0 github.com/gorilla/securecookie v1.1.1 @@ -19,17 +21,18 @@ require ( github.com/grpc-ecosystem/grpc-gateway v1.14.3 github.com/huandu/xstrings v1.3.0 // indirect github.com/imdario/mergo v0.3.8 // indirect - github.com/kr/pretty v0.1.0 // indirect github.com/mitchellh/copystructure v1.0.0 // indirect github.com/nicksnyder/go-i18n/v2 v2.0.3 + github.com/rs/cors v1.7.0 github.com/stretchr/testify v1.5.1 + go.opencensus.io v0.22.3 golang.org/x/crypto v0.0.0-20200320181102-891825fb96df golang.org/x/net v0.0.0-20200320220750-118fecf932d8 // indirect golang.org/x/sys v0.0.0-20200321134203-328b4cd54aae // indirect golang.org/x/text v0.3.2 - golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135 + golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56 + google.golang.org/api v0.20.0 // indirect google.golang.org/genproto v0.0.0-20200319113533-08878b785e9c // indirect google.golang.org/grpc v1.28.0 - gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect - gopkg.in/yaml.v2 v2.2.7 + gopkg.in/yaml.v2 v2.2.8 ) diff --git a/go.sum b/go.sum index e5db0f7feb..c277b44880 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,27 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.53.0 h1:MZQCQQaRwOrAcuKjiHWHrgKykt4fZyuwF2dtiG3fGW8= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +contrib.go.opencensus.io/exporter/stackdriver v0.13.0 h1:Jaz7WbqjtfoCPa1KbfisCX+P5aM3DizEY9pQMU0oAQo= +contrib.go.opencensus.io/exporter/stackdriver v0.13.0/go.mod h1:z2tyTZtPmQ2HvWH4cOmVDgtY+1lomfKdbLnkJvZdc8c= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.0/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= @@ -9,9 +29,16 @@ github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF0 github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60= github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q= +github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.29.16 h1:Gbtod7Y4W/Ai7wPtesdvgGVTkFN8JxAaGouRLlcQfQs= +github.com/aws/aws-sdk-go v1.29.16/go.mod h1:1KvfttTE3SPKMpo8g2c6jL3ZKfXtFvKscTgahTma5Xg= github.com/caos/logging v0.0.0-20191210002624-b3260f690a6a h1:HOU/3xL/afsZ+2aCstfJlrzRkwYMTFR1TIEgps5ny8s= github.com/caos/logging v0.0.0-20191210002624-b3260f690a6a/go.mod h1:9LKiDE2ChuGv6CHYif/kiugrfEXu9AwDiFWSreX7Wp0= +github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -23,25 +50,48 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3 h1:GV+pQPG/EUUbkh47niozDcADz6go/dUwhVzdUQHIVRw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gorilla/schema v1.1.0 h1:CamqUDOFUBqzrvxuz2vEwo8+SUdwsluFh7IlzJh30LY= github.com/gorilla/schema v1.1.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU= github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= @@ -50,10 +100,17 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.2.0 h1:0IKlLyQ3Hs9nDaiK5cSHAGmcQ github.com/grpc-ecosystem/go-grpc-middleware v1.2.0/go.mod h1:mJzapYve32yjrKlk9GbyCZHuPgZsrbyIbyKhSzOpg6s= github.com/grpc-ecosystem/grpc-gateway v1.14.3 h1:OCJlWkOUoTnl0neNGlf4fUm3TmbEtguw7vR+nGtnDjY= github.com/grpc-ecosystem/grpc-gateway v1.14.3/go.mod h1:6CwZWGDSPRJidgKAtJVvND6soZe6fT7iteq8wDPdhb0= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/huandu/xstrings v1.3.0 h1:gvV6jG9dTgFEncxo+AF7PH6MZXi/vZl25owA/8Dg8Wo= github.com/huandu/xstrings v1.3.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ= github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -73,10 +130,14 @@ github.com/nicksnyder/go-i18n/v2 v2.0.3 h1:ks/JkQiOEhhuF6jpNvx+Wih1NIiXzUnZeZVnJ github.com/nicksnyder/go-i18n/v2 v2.0.3/go.mod h1:oDab7q8XCYMRlcrBnaY/7B1eOectbvj6B1UPBT+p5jo= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= +github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -86,78 +147,197 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190506204251-e1dfcc566284/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200320181102-891825fb96df h1:lDWgvUvNnaTnNBc/dwOty86cFeKoKWbwy2wQj0gIxbU= golang.org/x/crypto v0.0.0-20200320181102-891825fb96df/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200320220750-118fecf932d8 h1:1+zQlQqEEhUeStBTi653GZAnAuivZq/2hz+Iz+OP7rg= golang.org/x/net v0.0.0-20200320220750-118fecf932d8/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191206220618-eeba5f6aabab h1:FvshnhkKW+LO3HWHodML8kuVX8rnJTxKm9dFPuI68UM= golang.org/x/sys v0.0.0-20191206220618-eeba5f6aabab/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200321134203-328b4cd54aae h1:3tcmuaB7wwSZtelmiv479UjUB+vviwABz7a133ZwOKQ= golang.org/x/sys v0.0.0-20200321134203-328b4cd54aae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135 h1:5Beo0mZN8dRzgrMMkDp0jc8YXQKx9DiJ2k1dkvGsn5A= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191010075000-0337d82405ff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56 h1:DFtSed2q3HtNuVazwVDZ4nSRS/JrZEig0gz2BY4VNrg= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.10.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0 h1:jz2KixHX7EcCPiQrySzPdnYT7DbINAypCqKZ1Z7GM40= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200319113533-08878b785e9c h1:5aI3/f/3eCZps9xwoEnmgfDJDhMbnJpfqeGpjVNgVEI= google.golang.org/genproto v0.0.0-20200319113533-08878b785e9c/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.28.0 h1:bO/TA4OxCOummhSf10siHuG7vJOiwh7SpRpFZDkOgl4= google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo= gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0 h1:9JKUTTIUgS6kzR9mK1YuGKv6Nl+DijDNIc0ghT58FaY= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4= diff --git a/internal/api/grpc/client/middleware/tracing.go b/internal/api/grpc/client/middleware/tracing.go new file mode 100644 index 0000000000..dbcfedcfac --- /dev/null +++ b/internal/api/grpc/client/middleware/tracing.go @@ -0,0 +1,38 @@ +package middleware + +import ( + "context" + "strings" + + "go.opencensus.io/plugin/ocgrpc" + "go.opencensus.io/trace" + "google.golang.org/grpc" + "google.golang.org/grpc/stats" + + "github.com/caos/zitadel/internal/api" + "github.com/caos/zitadel/internal/tracing" +) + +type GRPCMethod string + +func TracingStatsClient(ignoredMethods ...GRPCMethod) grpc.DialOption { + return grpc.WithStatsHandler(&tracingClientHandler{ignoredMethods, ocgrpc.ClientHandler{StartOptions: trace.StartOptions{Sampler: tracing.Sampler(), SpanKind: trace.SpanKindClient}}}) +} + +func DefaultTracingStatsClient() grpc.DialOption { + return TracingStatsClient(api.Healthz, api.Readiness, api.Validation) +} + +type tracingClientHandler struct { + IgnoredMethods []GRPCMethod + ocgrpc.ClientHandler +} + +func (s *tracingClientHandler) TagRPC(ctx context.Context, tagInfo *stats.RPCTagInfo) context.Context { + for _, method := range s.IgnoredMethods { + if strings.HasSuffix(tagInfo.FullMethodName, string(method)) { + return ctx + } + } + return s.ClientHandler.TagRPC(ctx, tagInfo) +} diff --git a/internal/api/grpc/server/gateway.go b/internal/api/grpc/server/gateway.go new file mode 100644 index 0000000000..955706b6ad --- /dev/null +++ b/internal/api/grpc/server/gateway.go @@ -0,0 +1,110 @@ +package server + +import ( + "context" + "net/http" + + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "google.golang.org/grpc" + + "github.com/caos/logging" + + client_middleware "github.com/caos/zitadel/internal/api/grpc/client/middleware" + http_util "github.com/caos/zitadel/internal/api/http" + http_mw "github.com/caos/zitadel/internal/api/http/middleware" +) + +const ( + defaultGatewayPort = "8080" + mimeWildcard = "*/*" +) + +var ( + DefaultJSONMarshaler = &runtime.JSONPb{OrigName: false, EmitDefaults: false} + + DefaultServeMuxOptions = []runtime.ServeMuxOption{ + runtime.WithMarshalerOption(DefaultJSONMarshaler.ContentType(), DefaultJSONMarshaler), + runtime.WithMarshalerOption(mimeWildcard, DefaultJSONMarshaler), + runtime.WithMarshalerOption(runtime.MIMEWildcard, DefaultJSONMarshaler), + runtime.WithIncomingHeaderMatcher(runtime.DefaultHeaderMatcher), + runtime.WithOutgoingHeaderMatcher(runtime.DefaultHeaderMatcher), + } +) + +type Gateway interface { + GRPCEndpoint() string + GatewayPort() string + Gateway() GatewayFunc +} + +type GatewayFunc func(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) error + +type gatewayCustomServeMuxOptions interface { + GatewayServeMuxOptions() []runtime.ServeMuxOption +} +type grpcGatewayCustomInterceptor interface { + GatewayHTTPInterceptor(http.Handler) http.Handler +} + +type gatewayCustomCallOptions interface { + GatewayCallOptions() []grpc.DialOption +} + +func StartGateway(ctx context.Context, g Gateway) { + mux := createMux(ctx, g) + serveGateway(ctx, mux, gatewayPort(g.GatewayPort()), g) +} + +func createMux(ctx context.Context, g Gateway) *runtime.ServeMux { + muxOptions := DefaultServeMuxOptions + if customOpts, ok := g.(gatewayCustomServeMuxOptions); ok { + muxOptions = customOpts.GatewayServeMuxOptions() + } + mux := runtime.NewServeMux(muxOptions...) + + opts := []grpc.DialOption{grpc.WithInsecure()} + opts = append(opts, client_middleware.DefaultTracingStatsClient()) + + if customOpts, ok := g.(gatewayCustomCallOptions); ok { + opts = append(opts, customOpts.GatewayCallOptions()...) + } + err := g.Gateway()(ctx, mux, g.GRPCEndpoint(), opts) + logging.Log("SERVE-7B7G0E").OnError(err).Panic("failed to create mux for grpc gateway") + + return mux +} + +func addInterceptors(handler http.Handler, g Gateway) http.Handler { + handler = http_mw.DefaultTraceHandler(handler) + if interceptor, ok := g.(grpcGatewayCustomInterceptor); ok { + handler = interceptor.GatewayHTTPInterceptor(handler) + } + return http_mw.CORSInterceptorOpts(http_mw.DefaultCORSOptions, handler) +} + +func serveGateway(ctx context.Context, handler http.Handler, port string, g Gateway) { + server := &http.Server{ + Handler: addInterceptors(handler, g), + } + + listener := http_util.CreateListener(port) + + go func() { + <-ctx.Done() + err := server.Shutdown(ctx) + logging.Log("SERVE-m7kBlq").OnError(err).Warn("error during graceful shutdown of grpc gateway") + }() + + go func() { + err := server.Serve(listener) + logging.Log("SERVE-tBHR60").OnError(err).Panic("grpc gateway serve failed") + }() + logging.LogWithFields("SERVE-KHh0Cb", "port", port).Info("grpc gateway is listening") +} + +func gatewayPort(port string) string { + if port == "" { + return defaultGatewayPort + } + return port +} diff --git a/internal/api/grpc/auth_interceptor.go b/internal/api/grpc/server/middleware/auth_interceptor.go similarity index 84% rename from internal/api/grpc/auth_interceptor.go rename to internal/api/grpc/server/middleware/auth_interceptor.go index 6ade793b1e..fbdd42bc9b 100644 --- a/internal/api/grpc/auth_interceptor.go +++ b/internal/api/grpc/server/middleware/auth_interceptor.go @@ -1,4 +1,4 @@ -package grpc +package middleware import ( "context" @@ -9,6 +9,7 @@ import ( "github.com/caos/zitadel/internal/api" "github.com/caos/zitadel/internal/api/auth" + grpc_util "github.com/caos/zitadel/internal/api/grpc" ) func AuthorizationInterceptor(verifier auth.TokenVerifier, authConfig *auth.Config, authMethods auth.MethodMapping) func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { @@ -18,12 +19,12 @@ func AuthorizationInterceptor(verifier auth.TokenVerifier, authConfig *auth.Conf return handler(ctx, req) } - authToken := GetAuthorizationHeader(ctx) + authToken := grpc_util.GetAuthorizationHeader(ctx) if authToken == "" { return nil, status.Error(codes.Unauthenticated, "auth header missing") } - orgID := GetHeader(ctx, api.ZitadelOrgID) + orgID := grpc_util.GetHeader(ctx, api.ZitadelOrgID) ctx, err := auth.CheckUserAuthorization(ctx, req, authToken, orgID, verifier, authConfig, authOpt) if err != nil { diff --git a/internal/api/grpc/error_interceptor.go b/internal/api/grpc/server/middleware/error_interceptor.go similarity index 74% rename from internal/api/grpc/error_interceptor.go rename to internal/api/grpc/server/middleware/error_interceptor.go index 690ab9a2e9..2d8f7f3e47 100644 --- a/internal/api/grpc/error_interceptor.go +++ b/internal/api/grpc/server/middleware/error_interceptor.go @@ -1,14 +1,16 @@ -package grpc +package middleware import ( "context" "google.golang.org/grpc" + + grpc_util "github.com/caos/zitadel/internal/api/grpc" ) func ErrorHandler() func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { resp, err := handler(ctx, req) - return resp, CaosToGRPCError(err) + return resp, grpc_util.CaosToGRPCError(err) } } diff --git a/internal/api/grpc/server/middleware/tracing.go b/internal/api/grpc/server/middleware/tracing.go new file mode 100644 index 0000000000..c8e2cc9d5d --- /dev/null +++ b/internal/api/grpc/server/middleware/tracing.go @@ -0,0 +1,33 @@ +package middleware + +import ( + "context" + "strings" + + "go.opencensus.io/plugin/ocgrpc" + "go.opencensus.io/trace" + "google.golang.org/grpc" + "google.golang.org/grpc/stats" + + "github.com/caos/zitadel/internal/tracing" +) + +type GRPCMethod string + +func TracingStatsServer(ignoredMethods ...GRPCMethod) grpc.ServerOption { + return grpc.StatsHandler(&tracingServerHandler{ignoredMethods, ocgrpc.ServerHandler{StartOptions: trace.StartOptions{Sampler: tracing.Sampler(), SpanKind: trace.SpanKindServer}}}) +} + +type tracingServerHandler struct { + IgnoredMethods []GRPCMethod + ocgrpc.ServerHandler +} + +func (s *tracingServerHandler) TagRPC(ctx context.Context, tagInfo *stats.RPCTagInfo) context.Context { + for _, method := range s.IgnoredMethods { + if strings.HasSuffix(tagInfo.FullMethodName, string(method)) { + return ctx + } + } + return s.ServerHandler.TagRPC(ctx, tagInfo) +} diff --git a/internal/api/grpc/probes.go b/internal/api/grpc/server/probes.go similarity index 98% rename from internal/api/grpc/probes.go rename to internal/api/grpc/server/probes.go index 8ec10c585c..91379da51e 100644 --- a/internal/api/grpc/probes.go +++ b/internal/api/grpc/server/probes.go @@ -1,4 +1,4 @@ -package grpc +package server import ( "context" diff --git a/internal/api/grpc/server/server.go b/internal/api/grpc/server/server.go new file mode 100644 index 0000000000..eb6f9f51f7 --- /dev/null +++ b/internal/api/grpc/server/server.go @@ -0,0 +1,53 @@ +package server + +import ( + "context" + "net" + + "github.com/caos/logging" + "google.golang.org/grpc" + + "github.com/caos/zitadel/internal/api/http" +) + +const ( + defaultGrpcPort = "80" +) + +type Server interface { + GRPCPort() string + GRPCServer() (*grpc.Server, error) +} + +func StartServer(ctx context.Context, s Server) { + port := grpcPort(s.GRPCPort()) + listener := http.CreateListener(port) + server := createGrpcServer(s) + serveServer(ctx, server, listener, port) +} + +func createGrpcServer(s Server) *grpc.Server { + grpcServer, err := s.GRPCServer() + logging.Log("SERVE-k280HZ").OnError(err).Panic("failed to create grpc server") + return grpcServer +} + +func serveServer(ctx context.Context, server *grpc.Server, listener net.Listener, port string) { + go func() { + <-ctx.Done() + server.GracefulStop() + }() + + go func() { + err := server.Serve(listener) + logging.Log("SERVE-Ga3e94").OnError(err).Panic("grpc server serve failed") + }() + logging.LogWithFields("SERVE-bZ44QM", "port", port).Info("grpc server is listening") +} + +func grpcPort(port string) string { + if port == "" { + return defaultGrpcPort + } + return port +} diff --git a/internal/api/header.go b/internal/api/header.go index fa8efc0282..857a91ff3b 100644 --- a/internal/api/header.go +++ b/internal/api/header.go @@ -2,7 +2,11 @@ package api const ( Authorization = "authorization" - AcceptLanguage = "Accept-Language" + Accept = "accept" + AcceptLanguage = "accept-language" + ContentType = "content-type" + Location = "location" + Origin = "origin" ZitadelOrgID = "x-zitadel-orgid" ) diff --git a/internal/api/http/listener.go b/internal/api/http/listener.go new file mode 100644 index 0000000000..3e9056c384 --- /dev/null +++ b/internal/api/http/listener.go @@ -0,0 +1,21 @@ +package http + +import ( + "net" + "strings" + + "github.com/caos/logging" +) + +func CreateListener(endpoint string) net.Listener { + l, err := net.Listen("tcp", listenerEndpoint(endpoint)) + logging.Log("SERVE-6vasef").OnError(err).Fatal("creating listener failed") + return l +} + +func listenerEndpoint(endpoint string) string { + if strings.Contains(endpoint, ":") { + return endpoint + } + return ":" + endpoint +} diff --git a/internal/api/http/middleware/cors_interceptor.go b/internal/api/http/middleware/cors_interceptor.go new file mode 100644 index 0000000000..6fd154b469 --- /dev/null +++ b/internal/api/http/middleware/cors_interceptor.go @@ -0,0 +1,47 @@ +package middleware + +import ( + "net/http" + + "github.com/rs/cors" + + "github.com/caos/zitadel/internal/api" +) + +var ( + DefaultCORSOptions = cors.Options{ + AllowCredentials: true, + AllowedHeaders: []string{ + api.Origin, + api.ContentType, + api.Accept, + api.AcceptLanguage, + api.Authorization, + api.ZitadelOrgID, + "x-grpc-web", //TODO: needed + }, + AllowedMethods: []string{ + http.MethodOptions, + http.MethodGet, + http.MethodHead, + http.MethodPost, + http.MethodPut, + http.MethodPatch, + http.MethodDelete, + }, + ExposedHeaders: []string{ + api.Location, + }, + AllowedOrigins: []string{ + "http://localhost:*", + }, + } +) + +func CORSInterceptorOpts(opts cors.Options, h http.Handler) http.Handler { + return cors.New(opts).Handler(h) +} + +func CORSInterceptor(h http.Handler) http.Handler { + return CORSInterceptorOpts(DefaultCORSOptions, h) +} diff --git a/internal/api/http/middleware/trace_interceptor.go b/internal/api/http/middleware/trace_interceptor.go new file mode 100644 index 0000000000..4f95cc67c1 --- /dev/null +++ b/internal/api/http/middleware/trace_interceptor.go @@ -0,0 +1,12 @@ +package middleware + +import ( + "net/http" + + "github.com/caos/zitadel/internal/api" + "github.com/caos/zitadel/internal/tracing" +) + +func DefaultTraceHandler(handler http.Handler) http.Handler { + return tracing.TraceHandler(handler, api.Probes...) +} diff --git a/internal/api/probes.go b/internal/api/probes.go new file mode 100644 index 0000000000..9ae0f6a1d9 --- /dev/null +++ b/internal/api/probes.go @@ -0,0 +1,11 @@ +package api + +const ( + Healthz = "/Healthz" + Readiness = "/Ready" + Validation = "/Validate" +) + +var ( + Probes = []string{Healthz, Readiness, Validation} +) diff --git a/internal/tracing/caller.go b/internal/tracing/caller.go new file mode 100644 index 0000000000..c5dfb9a319 --- /dev/null +++ b/internal/tracing/caller.go @@ -0,0 +1,24 @@ +package tracing + +import ( + "runtime" + + "github.com/caos/logging" +) + +func GetCaller() string { + fpcs := make([]uintptr, 1) + + n := runtime.Callers(3, fpcs) + if n == 0 { + logging.Log("HELPE-rWjfC").Debug("no caller") + } + + caller := runtime.FuncForPC(fpcs[0] - 1) + if caller == nil { + logging.Log("HELPE-25POw").Debug("caller was nil") + } + + // Print the name of the function + return caller.Name() +} diff --git a/internal/tracing/config/config.go b/internal/tracing/config/config.go new file mode 100644 index 0000000000..e2310fbce3 --- /dev/null +++ b/internal/tracing/config/config.go @@ -0,0 +1,61 @@ +package config + +import ( + "encoding/json" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + "github.com/caos/zitadel/internal/tracing" + tracing_g "github.com/caos/zitadel/internal/tracing/google" + tracing_log "github.com/caos/zitadel/internal/tracing/log" +) + +type TracingConfig struct { + Type string + Config tracing.Config +} + +var tracer = map[string]func() tracing.Config{ + "google": func() tracing.Config { return &tracing_g.Config{} }, + "log": func() tracing.Config { return &tracing_log.Config{} }, +} + +func (c *TracingConfig) UnmarshalJSON(data []byte) error { + var rc struct { + Type string + Config json.RawMessage + } + + if err := json.Unmarshal(data, &rc); err != nil { + return status.Errorf(codes.Internal, "%v parse config: %v", "TRACE-vmjS", err) + } + + c.Type = rc.Type + + var err error + c.Config, err = newTracingConfig(c.Type, rc.Config) + if err != nil { + return status.Errorf(codes.Internal, "%v parse config: %v", "TRACE-Ws9E", err) + } + + return c.Config.NewTracer() +} + +func newTracingConfig(tracerType string, configData []byte) (tracing.Config, error) { + t, ok := tracer[tracerType] + if !ok { + return nil, status.Errorf(codes.Internal, "%v No config: %v", "TRACE-HMEJ", tracerType) + } + + tracingConfig := t() + if len(configData) == 0 { + return tracingConfig, nil + } + + if err := json.Unmarshal(configData, tracingConfig); err != nil { + return nil, status.Errorf(codes.Internal, "%v Could not read conifg: %v", "TRACE-1tSS", err) + } + + return tracingConfig, nil +} diff --git a/internal/tracing/generate.go b/internal/tracing/generate.go new file mode 100644 index 0000000000..21b97622cb --- /dev/null +++ b/internal/tracing/generate.go @@ -0,0 +1,3 @@ +package tracing + +//go:generate mockgen -package mock -destination mock/tracing_mock.go github.com/caos/zitadel/internal/tracing Tracer diff --git a/internal/tracing/google/config.go b/internal/tracing/google/config.go new file mode 100644 index 0000000000..92d93f61bd --- /dev/null +++ b/internal/tracing/google/config.go @@ -0,0 +1,25 @@ +package google + +import ( + "go.opencensus.io/trace" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + "github.com/caos/zitadel/internal/tracing" +) + +type Config struct { + ProjectID string + MetricPrefix string + Fraction float64 +} + +func (c *Config) NewTracer() error { + if !envIsSet() { + return status.Error(codes.InvalidArgument, "env not properly set, GOOGLE_APPLICATION_CREDENTIALS is misconfigured or missing") + } + + tracing.T = &Tracer{projectID: c.ProjectID, metricPrefix: c.MetricPrefix, sampler: trace.ProbabilitySampler(c.Fraction)} + + return tracing.T.Start() +} diff --git a/internal/tracing/google/googletracing.go b/internal/tracing/google/googletracing.go new file mode 100644 index 0000000000..3958592d00 --- /dev/null +++ b/internal/tracing/google/googletracing.go @@ -0,0 +1,95 @@ +package google + +import ( + "context" + "net/http" + "os" + "strings" + + "contrib.go.opencensus.io/exporter/stackdriver" + "go.opencensus.io/plugin/ocgrpc" + "go.opencensus.io/plugin/ochttp" + "go.opencensus.io/stats/view" + "go.opencensus.io/trace" + + "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/tracing" +) + +type Tracer struct { + Exporter *stackdriver.Exporter + projectID string + metricPrefix string + sampler trace.Sampler +} + +func (t *Tracer) Start() (err error) { + t.Exporter, err = stackdriver.NewExporter(stackdriver.Options{ + ProjectID: t.projectID, + MetricPrefix: t.metricPrefix, + }) + if err != nil { + return errors.ThrowInternal(err, "GOOGL-4dCnX", "unable to start exporter") + } + + views := append(ocgrpc.DefaultServerViews, ocgrpc.DefaultClientViews...) + views = append(views, ochttp.DefaultClientViews...) + views = append(views, ochttp.DefaultServerViews...) + + if err = view.Register(views...); err != nil { + return errors.ThrowInternal(err, "GOOGL-Q6L6w", "unable to register view") + } + + trace.RegisterExporter(t.Exporter) + trace.ApplyConfig(trace.Config{DefaultSampler: t.sampler}) + + return nil +} + +func (t *Tracer) Sampler() trace.Sampler { + return t.sampler +} + +func (t *Tracer) NewServerInterceptorSpan(ctx context.Context, name string) (context.Context, *tracing.Span) { + return t.newSpanFromName(ctx, name, trace.WithSpanKind(trace.SpanKindServer)) +} + +func (t *Tracer) NewServerSpan(ctx context.Context, caller string) (context.Context, *tracing.Span) { + return t.newSpan(ctx, caller, trace.WithSpanKind(trace.SpanKindServer)) +} + +func (t *Tracer) NewClientInterceptorSpan(ctx context.Context, name string) (context.Context, *tracing.Span) { + return t.newSpanFromName(ctx, name, trace.WithSpanKind(trace.SpanKindClient)) +} + +func (t *Tracer) NewClientSpan(ctx context.Context, caller string) (context.Context, *tracing.Span) { + return t.newSpan(ctx, caller, trace.WithSpanKind(trace.SpanKindClient)) +} + +func (t *Tracer) NewSpan(ctx context.Context, caller string) (context.Context, *tracing.Span) { + return t.newSpan(ctx, caller) +} + +func (t *Tracer) newSpan(ctx context.Context, caller string, options ...trace.StartOption) (context.Context, *tracing.Span) { + return t.newSpanFromName(ctx, caller, options...) +} + +func (t *Tracer) newSpanFromName(ctx context.Context, name string, options ...trace.StartOption) (context.Context, *tracing.Span) { + ctx, span := trace.StartSpan(ctx, name, options...) + return ctx, tracing.CreateSpan(span) +} + +func (t *Tracer) NewSpanHTTP(r *http.Request, caller string) (*http.Request, *tracing.Span) { + ctx, span := t.NewSpan(r.Context(), caller) + r = r.WithContext(ctx) + return r, span +} + +func envIsSet() bool { + gAuthCred := os.Getenv("GOOGLE_APPLICATION_CREDENTIALS") + return strings.Contains(gAuthCred, ".json") +} + +func (t *Tracer) SetErrStatus(span *trace.Span, code int32, err error, obj ...string) { + span.SetStatus(trace.Status{Code: code, Message: err.Error() + strings.Join(obj, ", ")}) +} diff --git a/internal/tracing/http_handler.go b/internal/tracing/http_handler.go new file mode 100644 index 0000000000..a3b9631863 --- /dev/null +++ b/internal/tracing/http_handler.go @@ -0,0 +1,30 @@ +package tracing + +import ( + "net/http" + "strings" + + "go.opencensus.io/plugin/ochttp" + "go.opencensus.io/trace" +) + +func TraceHandler(handler http.Handler, ignoredMethods ...string) http.Handler { + healthEndpoints := strings.Join(ignoredMethods, ";;") + + return &ochttp.Handler{ + Handler: handler, + FormatSpanName: func(r *http.Request) string { + host := r.URL.Host + if host == "" { + host = r.Host + } + return host + r.URL.Path + }, + + StartOptions: trace.StartOptions{Sampler: Sampler()}, + IsHealthEndpoint: func(r *http.Request) bool { + n := strings.Contains(healthEndpoints, r.URL.RequestURI()) + return n + }, + } +} diff --git a/internal/tracing/log/config.go b/internal/tracing/log/config.go new file mode 100644 index 0000000000..be2d9bec7a --- /dev/null +++ b/internal/tracing/log/config.go @@ -0,0 +1,21 @@ +package log + +import ( + "go.opencensus.io/trace" + + "github.com/caos/zitadel/internal/tracing" +) + +type Config struct { + Fraction float64 +} + +func (c *Config) NewTracer() error { + if c.Fraction < 1 { + c.Fraction = 1 + } + + tracing.T = &Tracer{trace.ProbabilitySampler(c.Fraction)} + + return tracing.T.Start() +} diff --git a/internal/tracing/log/logTracing.go b/internal/tracing/log/logTracing.go new file mode 100644 index 0000000000..ce34c68fce --- /dev/null +++ b/internal/tracing/log/logTracing.go @@ -0,0 +1,74 @@ +package log + +import ( + "context" + "net/http" + + "go.opencensus.io/examples/exporter" + "go.opencensus.io/plugin/ocgrpc" + "go.opencensus.io/plugin/ochttp" + "go.opencensus.io/stats/view" + "go.opencensus.io/trace" + + "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/tracing" +) + +type Tracer struct { + sampler trace.Sampler +} + +func (t *Tracer) Start() error { + trace.RegisterExporter(&exporter.PrintExporter{}) + + views := append(ocgrpc.DefaultServerViews, ocgrpc.DefaultClientViews...) + views = append(views, ochttp.DefaultClientViews...) + views = append(views, ochttp.DefaultServerViews...) + + if err := view.Register(views...); err != nil { + return errors.ThrowInternal(err, "LOG-PoFiB", "unable to register view") + } + + trace.ApplyConfig(trace.Config{DefaultSampler: t.sampler}) + + return nil +} + +func (t *Tracer) Sampler() trace.Sampler { + return t.sampler +} + +func (t *Tracer) NewServerInterceptorSpan(ctx context.Context, name string) (context.Context, *tracing.Span) { + return t.newSpanFromName(ctx, name, trace.WithSpanKind(trace.SpanKindServer)) +} + +func (t *Tracer) NewServerSpan(ctx context.Context, caller string) (context.Context, *tracing.Span) { + return t.newSpan(ctx, caller, trace.WithSpanKind(trace.SpanKindServer)) +} + +func (t *Tracer) NewClientInterceptorSpan(ctx context.Context, name string) (context.Context, *tracing.Span) { + return t.newSpanFromName(ctx, name, trace.WithSpanKind(trace.SpanKindClient)) +} + +func (t *Tracer) NewClientSpan(ctx context.Context, caller string) (context.Context, *tracing.Span) { + return t.newSpan(ctx, caller, trace.WithSpanKind(trace.SpanKindClient)) +} + +func (t *Tracer) NewSpan(ctx context.Context, caller string) (context.Context, *tracing.Span) { + return t.newSpan(ctx, caller) +} + +func (t *Tracer) newSpan(ctx context.Context, caller string, options ...trace.StartOption) (context.Context, *tracing.Span) { + return t.newSpanFromName(ctx, caller, options...) +} + +func (t *Tracer) newSpanFromName(ctx context.Context, name string, options ...trace.StartOption) (context.Context, *tracing.Span) { + ctx, span := trace.StartSpan(ctx, name, options...) + return ctx, tracing.CreateSpan(span) +} + +func (t *Tracer) NewSpanHTTP(r *http.Request, caller string) (*http.Request, *tracing.Span) { + ctx, span := t.NewSpan(r.Context(), caller) + r = r.WithContext(ctx) + return r, span +} diff --git a/internal/tracing/mock/tracing_mock.go b/internal/tracing/mock/tracing_mock.go new file mode 100644 index 0000000000..d765782360 --- /dev/null +++ b/internal/tracing/mock/tracing_mock.go @@ -0,0 +1,155 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/caos/zitadel/internal/tracing (interfaces: Tracer) + +// Package mock is a generated GoMock package. +package mock + +import ( + context "context" + tracing "github.com/caos/zitadel/internal/tracing" + gomock "github.com/golang/mock/gomock" + trace "go.opencensus.io/trace" + http "net/http" + reflect "reflect" +) + +// MockTracer is a mock of Tracer interface +type MockTracer struct { + ctrl *gomock.Controller + recorder *MockTracerMockRecorder +} + +// MockTracerMockRecorder is the mock recorder for MockTracer +type MockTracerMockRecorder struct { + mock *MockTracer +} + +// NewMockTracer creates a new mock instance +func NewMockTracer(ctrl *gomock.Controller) *MockTracer { + mock := &MockTracer{ctrl: ctrl} + mock.recorder = &MockTracerMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockTracer) EXPECT() *MockTracerMockRecorder { + return m.recorder +} + +// NewClientInterceptorSpan mocks base method +func (m *MockTracer) NewClientInterceptorSpan(arg0 context.Context, arg1 string) (context.Context, *tracing.Span) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "NewClientInterceptorSpan", arg0, arg1) + ret0, _ := ret[0].(context.Context) + ret1, _ := ret[1].(*tracing.Span) + return ret0, ret1 +} + +// NewClientInterceptorSpan indicates an expected call of NewClientInterceptorSpan +func (mr *MockTracerMockRecorder) NewClientInterceptorSpan(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewClientInterceptorSpan", reflect.TypeOf((*MockTracer)(nil).NewClientInterceptorSpan), arg0, arg1) +} + +// NewClientSpan mocks base method +func (m *MockTracer) NewClientSpan(arg0 context.Context, arg1 string) (context.Context, *tracing.Span) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "NewClientSpan", arg0, arg1) + ret0, _ := ret[0].(context.Context) + ret1, _ := ret[1].(*tracing.Span) + return ret0, ret1 +} + +// NewClientSpan indicates an expected call of NewClientSpan +func (mr *MockTracerMockRecorder) NewClientSpan(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewClientSpan", reflect.TypeOf((*MockTracer)(nil).NewClientSpan), arg0, arg1) +} + +// NewServerInterceptorSpan mocks base method +func (m *MockTracer) NewServerInterceptorSpan(arg0 context.Context, arg1 string) (context.Context, *tracing.Span) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "NewServerInterceptorSpan", arg0, arg1) + ret0, _ := ret[0].(context.Context) + ret1, _ := ret[1].(*tracing.Span) + return ret0, ret1 +} + +// NewServerInterceptorSpan indicates an expected call of NewServerInterceptorSpan +func (mr *MockTracerMockRecorder) NewServerInterceptorSpan(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewServerInterceptorSpan", reflect.TypeOf((*MockTracer)(nil).NewServerInterceptorSpan), arg0, arg1) +} + +// NewServerSpan mocks base method +func (m *MockTracer) NewServerSpan(arg0 context.Context, arg1 string) (context.Context, *tracing.Span) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "NewServerSpan", arg0, arg1) + ret0, _ := ret[0].(context.Context) + ret1, _ := ret[1].(*tracing.Span) + return ret0, ret1 +} + +// NewServerSpan indicates an expected call of NewServerSpan +func (mr *MockTracerMockRecorder) NewServerSpan(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewServerSpan", reflect.TypeOf((*MockTracer)(nil).NewServerSpan), arg0, arg1) +} + +// NewSpan mocks base method +func (m *MockTracer) NewSpan(arg0 context.Context, arg1 string) (context.Context, *tracing.Span) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "NewSpan", arg0, arg1) + ret0, _ := ret[0].(context.Context) + ret1, _ := ret[1].(*tracing.Span) + return ret0, ret1 +} + +// NewSpan indicates an expected call of NewSpan +func (mr *MockTracerMockRecorder) NewSpan(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewSpan", reflect.TypeOf((*MockTracer)(nil).NewSpan), arg0, arg1) +} + +// NewSpanHTTP mocks base method +func (m *MockTracer) NewSpanHTTP(arg0 *http.Request, arg1 string) (*http.Request, *tracing.Span) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "NewSpanHTTP", arg0, arg1) + ret0, _ := ret[0].(*http.Request) + ret1, _ := ret[1].(*tracing.Span) + return ret0, ret1 +} + +// NewSpanHTTP indicates an expected call of NewSpanHTTP +func (mr *MockTracerMockRecorder) NewSpanHTTP(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewSpanHTTP", reflect.TypeOf((*MockTracer)(nil).NewSpanHTTP), arg0, arg1) +} + +// Sampler mocks base method +func (m *MockTracer) Sampler() trace.Sampler { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Sampler") + ret0, _ := ret[0].(trace.Sampler) + return ret0 +} + +// Sampler indicates an expected call of Sampler +func (mr *MockTracerMockRecorder) Sampler() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Sampler", reflect.TypeOf((*MockTracer)(nil).Sampler)) +} + +// Start mocks base method +func (m *MockTracer) Start() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Start") + ret0, _ := ret[0].(error) + return ret0 +} + +// Start indicates an expected call of Start +func (mr *MockTracerMockRecorder) Start() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Start", reflect.TypeOf((*MockTracer)(nil).Start)) +} diff --git a/internal/tracing/mock/tracing_mock_impl.go b/internal/tracing/mock/tracing_mock_impl.go new file mode 100644 index 0000000000..7e7335d851 --- /dev/null +++ b/internal/tracing/mock/tracing_mock_impl.go @@ -0,0 +1,20 @@ +package mock + +import ( + "context" + "testing" + + "github.com/golang/mock/gomock" + + "github.com/caos/zitadel/internal/tracing" +) + +func NewSimpleMockTracer(t *testing.T) *MockTracer { + return NewMockTracer(gomock.NewController(t)) +} + +func ExpectServerSpan(ctx context.Context, mock interface{}) { + m := mock.(*MockTracer) + any := gomock.Any() + m.EXPECT().NewServerSpan(any, any).AnyTimes().Return(ctx, &tracing.Span{}) +} diff --git a/internal/tracing/span.go b/internal/tracing/span.go new file mode 100644 index 0000000000..d958cb4b52 --- /dev/null +++ b/internal/tracing/span.go @@ -0,0 +1,89 @@ +package tracing + +import ( + "fmt" + "strconv" + + "go.opencensus.io/trace" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +type Span struct { + span *trace.Span + attributes []trace.Attribute +} + +func CreateSpan(span *trace.Span) *Span { + return &Span{span: span, attributes: []trace.Attribute{}} +} + +func (s *Span) End() { + if s.span == nil { + return + } + s.span.AddAttributes(s.attributes...) + s.span.End() +} + +func (s *Span) EndWithError(err error) { + s.SetStatusByError(err) + s.End() +} + +func (s *Span) SetStatusByError(err error) { + if s.span == nil { + return + } + s.span.SetStatus(statusFromError(err)) +} + +func statusFromError(err error) trace.Status { + if statusErr, ok := status.FromError(err); ok { + return trace.Status{Code: int32(statusErr.Code()), Message: statusErr.Message()} + } + return trace.Status{Code: int32(codes.Unknown), Message: "Unknown"} +} + +// AddAnnotation creates an annotation. The annotation will not be added to the tracing use Annotate(msg) afterwards +func (s *Span) AddAnnotation(key string, value interface{}) *Span { + attribute, err := toTraceAttribute(key, value) + if err != nil { + return s + } + s.attributes = append(s.attributes, attribute) + return s +} + +// Annotate creates an annotation in tracing. Before added annotations will be set +func (s *Span) Annotate(message string) *Span { + if s.span == nil { + return s + } + s.span.Annotate(s.attributes, message) + s.attributes = []trace.Attribute{} + return s +} + +func (s *Span) Annotatef(format string, addiations ...interface{}) *Span { + s.Annotate(fmt.Sprintf(format, addiations...)) + return s +} + +func toTraceAttribute(key string, value interface{}) (attr trace.Attribute, err error) { + switch value := value.(type) { + case bool: + return trace.BoolAttribute(key, value), nil + case string: + return trace.StringAttribute(key, value), nil + } + if valueInt, err := convertToInt64(value); err == nil { + return trace.Int64Attribute(key, valueInt), nil + } + return attr, status.Error(codes.InvalidArgument, "Attribute is not of type bool, string or int64") +} + +func convertToInt64(value interface{}) (int64, error) { + valueString := fmt.Sprintf("%v", value) + return strconv.ParseInt(valueString, 10, 64) +} diff --git a/internal/tracing/tracing.go b/internal/tracing/tracing.go new file mode 100644 index 0000000000..61fdc4b318 --- /dev/null +++ b/internal/tracing/tracing.go @@ -0,0 +1,74 @@ +package tracing + +import ( + "context" + "net/http" + + "go.opencensus.io/trace" +) + +type Tracer interface { + Start() error + NewSpan(ctx context.Context, caller string) (context.Context, *Span) + NewClientSpan(ctx context.Context, caller string) (context.Context, *Span) + NewServerSpan(ctx context.Context, caller string) (context.Context, *Span) + NewClientInterceptorSpan(ctx context.Context, name string) (context.Context, *Span) + NewServerInterceptorSpan(ctx context.Context, name string) (context.Context, *Span) + NewSpanHTTP(r *http.Request, caller string) (*http.Request, *Span) + Sampler() trace.Sampler +} + +type Config interface { + NewTracer() error +} + +var T Tracer + +func Sampler() trace.Sampler { + if T == nil { + return trace.NeverSample() + } + return T.Sampler() +} + +func NewSpan(ctx context.Context) (context.Context, *Span) { + if T == nil { + return ctx, CreateSpan(nil) + } + return T.NewSpan(ctx, GetCaller()) +} + +func NewClientSpan(ctx context.Context) (context.Context, *Span) { + if T == nil { + return ctx, CreateSpan(nil) + } + return T.NewClientSpan(ctx, GetCaller()) +} + +func NewServerSpan(ctx context.Context) (context.Context, *Span) { + if T == nil { + return ctx, CreateSpan(nil) + } + return T.NewServerSpan(ctx, GetCaller()) +} + +func NewClientInterceptorSpan(ctx context.Context, name string) (context.Context, *Span) { + if T == nil { + return ctx, CreateSpan(nil) + } + return T.NewClientInterceptorSpan(ctx, name) +} + +func NewServerInterceptorSpan(ctx context.Context, name string) (context.Context, *Span) { + if T == nil { + return ctx, CreateSpan(nil) + } + return T.NewServerInterceptorSpan(ctx, name) +} + +func NewSpanHTTP(r *http.Request) (*http.Request, *Span) { + if T == nil { + return r, CreateSpan(nil) + } + return T.NewSpanHTTP(r, GetCaller()) +} From 5cd9ca506aca33e9e816883e9944f27532772151 Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Wed, 25 Mar 2020 07:58:58 +0100 Subject: [PATCH 18/39] add basic config and change i18n pkg --- cmd/zitadel/authz.yaml | 295 ++++++++++++++++++++++++++++++++++ cmd/zitadel/main.go | 38 +++-- cmd/zitadel/startup.yaml | 44 +++++ go.mod | 3 +- internal/admin/config.go | 4 + internal/api/grpc/config.go | 34 ++++ internal/api/html/i18n.go | 7 +- internal/auth/config.go | 4 + internal/config/config.go | 4 +- internal/config/flag.go | 14 ++ internal/login/config.go | 4 + internal/management/config.go | 3 + pkg/admin/admin.go | 7 +- pkg/admin/api/config.go | 7 + pkg/auth/api/config.go | 7 + pkg/auth/auth.go | 7 +- pkg/console/console.go | 16 ++ pkg/login/api/config.go | 4 + pkg/login/login.go | 18 +++ pkg/management/api/config.go | 7 + pkg/management/management.go | 7 +- 21 files changed, 515 insertions(+), 19 deletions(-) create mode 100644 cmd/zitadel/authz.yaml create mode 100644 cmd/zitadel/startup.yaml create mode 100644 internal/admin/config.go create mode 100644 internal/api/grpc/config.go create mode 100644 internal/auth/config.go create mode 100644 internal/config/flag.go create mode 100644 internal/login/config.go create mode 100644 internal/management/config.go create mode 100644 pkg/admin/api/config.go create mode 100644 pkg/auth/api/config.go create mode 100644 pkg/console/console.go create mode 100644 pkg/login/api/config.go create mode 100644 pkg/login/login.go create mode 100644 pkg/management/api/config.go diff --git a/cmd/zitadel/authz.yaml b/cmd/zitadel/authz.yaml new file mode 100644 index 0000000000..ac5b8ebd72 --- /dev/null +++ b/cmd/zitadel/authz.yaml @@ -0,0 +1,295 @@ +AuthZ: + RolePermissionMappings: + - Role: 'IAM_OWNER' + Permissions: + - "org.read" + - "org.write" + - "org.member.read" + - "org.member.write" + - "org.member.delete" + - "user.read" + - "user.write" + - "user.delete" + - "user.grant.read" + - "user.grant.write" + - "policy.read" + - "policy.write" + - "policy.delete" + - "project.read" + - "project.write" + - "project.member.read" + - "project.member.write" + - "project.member.delete" + - "project.role.read" + - "project.role.write" + - "project.role.delete" + - "project.app.read" + - "project.app.write" + - "project.grant.read" + - "project.grant.write" + - "project.grant.member.read" + - "project.grant.member.write" + - "project.grant.member.delete" + - Role: 'ORG_OWNER' + Permissions: + - "org.read" + - "org.write" + - "org.member.read" + - "org.member.write" + - "org.member.delete" + - "user.read" + - "user.write" + - "user.delete" + - "user.grant.read" + - "user.grant.write" + - "policy.read" + - "policy.write" + - "policy.delete" + - "project.read" + - "project.write" + - "project.member.read" + - "project.member.write" + - "project.member.delete" + - "project.role.read" + - "project.role.write" + - "project.role.delete" + - "project.app.read" + - "project.app.write" + - "project.grant.read" + - "project.grant.write" + - "project.grant.member.read" + - "project.grant.member.write" + - "project.grant.member.delete" + - Role: 'ORG_EDITOR' + Permissions: + - "org.read" + - "org.write" + - Role: 'ORG_VIEWER' + Permissions: + - "org.read" + - Role: 'ORG_MEMBER_EDITOR' + Permissions: + - "org.read" + - "org.member.read" + - "org.member.write" + - "org.member.delete" + - Role: 'ORG_MEMBER_VIEWER' + Permissions: + - "org.read" + - "org.member.read" + - Role: 'ORG_PROJECT_CREATOR' + Permissions: + - "project.read:self" + - "project.write" + - Role: 'ORG_PROJECT_EDITOR' + Permissions: + - "project.read" + - "project.write" + - "project.member.read" + - "project.member.write" + - "project.member.delete" + - "project.role.read" + - "project.role.write" + - "project.role.delete" + - "project.app.read" + - "project.app.write" + - "project.grant.read" + - "project.grant.write" + - "project.grant.member.read" + - "project.grant.member.write" + - "project.grant.member.delete" + - Role: 'ORG_PROJECT_VIEWER' + Permissions: + - "project.read" + - "project.member.read" + - "project.role.read" + - "project.app.read" + - "project.grant.read" + - "project.grant.member.read" + - Role: 'ORG_PROJECT_MEMBER_EDITOR' + Permissions: + - "project.read" + - "project.member.read" + - "project.member.write" + - "project.grant.member.delete" + - Role: 'ORG_PROJECT_MEMBER_VIEWER' + Permissions: + - "project.read" + - "project.member.read" + - Role: 'ORG_PROJECT_ROLE_EDITOR' + Permissions: + - "project.read" + - "project.role.read" + - "project.role.write" + - "project.role.delete" + - Role: 'ORG_PROJECT_ROLE_VIEWER' + Permissions: + - "project.read" + - "project.role.read" + - Role: 'ORG_PROJECT_APP_EDITOR' + Permissions: + - "project.read" + - "project.app.read" + - "project.app.write" + - Role: 'ORG_PROJECT_APP_VIEWER' + Permissions: + - "project.read" + - "project.app.read" + - Role: 'ORG_PROJECT_GRANT_EDITOR' + Permissions: + - "project.read" + - "project.grant.read" + - "project.grant.write" + - "project.grant.member.read" + - "project.grant.member.write" + - "project.grant.member.delete" + - Role: 'ORG_PROJECT_GRANT_VIEWER' + Permissions: + - "project.read" + - "project.grant.read" + - Role: 'ORG_PROJECT_GRANT_MEMBER_EDITOR' + Permissions: + - "project.read" + - "project.grant.read" + - "project.grant.member.read" + - "project.grant.member.write" + - "project.grant.member.delete" + - Role: 'ORG_PROJECT_GRANT_MEMBER_VIEWER' + Permissions: + - "project.read" + - "project.grant.read" + - "project.grant.member.read" + - Role: 'ORG_USER_EDITOR' + Permissions: + - "user.read" + - "user.write" + - "user.delete" + - Role: 'ORG_USER_VIEWER' + Permissions: + - "user.read" + - Role: 'ORG_USER_GRANT_EDITOR' + Permissions: + - "user.read" + - "user.grant.read" + - "user.grant.write" + - "project.read" + - Role: 'ORG_USER_GRANT_VIEWER' + Permissions: + - "user.read" + - "user.grant.read" + - Role: 'ORG_POLICY_EDITOR' + Permissions: + - "policy.read" + - "policy.write" + - "policy.delete" + - Role: 'ORG_POLICY_VIEWER' + Permissions: + - "policy.read" + - Role: 'PROJECT_OWNER' + Permissions: + - "project.read" + - "project.write" + - "project.member.read" + - "project.member.write" + - "project.member.delete" + - "project.role.read" + - "project.role.write" + - "project.role.delete" + - "project.app.read" + - "project.app.write" + - "project.grant.read" + - "project.grant.write" + - "project.grant.member.read" + - "project.grant.member.write" + - "project.grant.member.delete" + - "project.user.grant.read" + - "project.user.grant.write" + - "project.user.grant.delete" + - Role: 'PROJECT_MEMBER_EDITOR' + Permissions: + - "project.read" + - "project.member.read" + - "project.member.write" + - "project.member.delete" + - Role: 'PROJECT_MEMBER_VIEWER' + Permissions: + - "project.read" + - "project.member.read" + - Role: 'PROJECT_ROLE_EDITOR' + Permissions: + - "project.read" + - "project.role.read" + - "project.role.write" + - "project.role.delete" + - Role: 'PROJECT_APP_EDITOR' + Permissions: + - "project.read" + - "project.app.read" + - "project.app.write" + - Role: 'PROJECT_APP_VIEWER' + Permissions: + - "project.read" + - "project.app.read" + - Role: 'PROJECT_GRANT_EDITOR' + Permissions: + - "project.read" + - "project.grant.read" + - "project.grant.write" + - Role: 'PROJECT_GRANT_VIEWER' + Permissions: + - "project.read" + - "project.grant.read" + - Role: 'PROJECT_GRANT_MEMBER_EDITOR' + Permissions: + - "project.read" + - "project.grant.read" + - "project.grant.member.read" + - "project.grant.member.write" + - "project.grant.member.delete" + - Role: 'PROJECT_GRANT_MEMBER_VIEWER' + Permissions: + - "project.read" + - "project.grant.read" + - "project.grant.member.read" + - Role: 'PROJECT_USER_GRANT_EDITOR' + Permissions: + - "project.read" + - "project.user.grant.read" + - "project.user.grant.write" + - "project.user.grant.delete" + - Role: 'PROJECT_USER_GRANT_VIEWER' + Permissions: + - "project.read" + - "project.user.grant.read" + - Role: 'PROJECT_GRANT_OWNER' + Permissions: + - "project.read" + - "project.grant.read" + - "project.grant.write" + - "project.grant.member.read" + - "project.grant.member.write" + - "project.grant.member.delete" + - Role: 'PROJECT_GRANT_MEMBER_EDITOR' + Permissions: + - "project.read" + - "project.grant.read" + - "project.grant.member.read" + - "project.grant.member.write" + - "project.grant.member.delete" + - Role: 'PROJECT_GRANT_MEMBER_VIEWER' + Permissions: + - "project.read" + - "project.grant.read" + - "project.grant.member.read" + - Role: 'PROJECT_GRANT_USER_GRANT_EDITOR' + Permissions: + - "project.read" + - "project.grant.read" + - "project.grant.user.grant.read" + - "project.grant.user.grant.write" + - "project.grant.user.grant.delete" + - Role: 'PROJECT_GRANT_USER_GRANT_VIEWER' + Permissions: + - "project.read" + - "project.grant.read" + - "project.grant.user.grant.read" diff --git a/cmd/zitadel/main.go b/cmd/zitadel/main.go index f44be202ab..4c3137b9c6 100644 --- a/cmd/zitadel/main.go +++ b/cmd/zitadel/main.go @@ -6,45 +6,63 @@ import ( "github.com/caos/logging" + authz "github.com/caos/zitadel/internal/api/auth" "github.com/caos/zitadel/internal/config" "github.com/caos/zitadel/pkg/admin" "github.com/caos/zitadel/pkg/auth" - "github.com/caos/zitadel/pkg/eventstore" + "github.com/caos/zitadel/pkg/console" + "github.com/caos/zitadel/pkg/login" "github.com/caos/zitadel/pkg/management" ) type Config struct { - Eventstore eventstore.Config - Management management.Config - Auth auth.Config - Admin admin.Config + Mgmt *management.Config + Auth *auth.Config + Login *login.Config + Admin *admin.Config + Console *console.Config + + //Log + //Tracing tracing.TracingConfig + AuthZ *authz.Config } func main() { - configPath := flag.String("config-file", "/zitadel/config/startup.yaml", "path to the config file") + var configPaths config.ArrayFlags + flag.Var(&configPaths, "config-files", "path to the config files") managementEnabled := flag.Bool("management", true, "enable management api") authEnabled := flag.Bool("auth", true, "enable auth api") + loginEnabled := flag.Bool("login", true, "enable login ui") adminEnabled := flag.Bool("admin", true, "enable admin api") + consoleEnabled := flag.Bool("console", true, "enable console ui") flag.Parse() conf := new(Config) - err := config.Read(conf, *configPath) + err := config.Read(conf, configPaths...) logging.Log("MAIN-FaF2r").OnError(err).Fatal("cannot read config") ctx := context.Background() if *managementEnabled { - err = management.Start(ctx, conf.Management) + err = management.Start(ctx, conf.Mgmt, conf.AuthZ) logging.Log("MAIN-39Nv5").OnError(err).Fatal("error starting management api") } if *authEnabled { - err = auth.Start(ctx, conf.Auth) + err = auth.Start(ctx, conf.Auth, conf.AuthZ) logging.Log("MAIN-x0nD2").OnError(err).Fatal("error starting auth api") } + if *loginEnabled { + err = login.Start(ctx, conf.Login) + logging.Log("MAIN-53RF2").OnError(err).Fatal("error starting login ui") + } if *adminEnabled { - err = admin.Start(ctx, conf.Admin) + err = admin.Start(ctx, conf.Admin, conf.AuthZ) logging.Log("MAIN-0na71").OnError(err).Fatal("error starting admin api") } + if *consoleEnabled { + err = console.Start(ctx, conf.Console) + logging.Log("MAIN-3Dfuc").OnError(err).Fatal("error starting console ui") + } <-ctx.Done() logging.Log("MAIN-s8d2h").Info("stopping zitadel") } diff --git a/cmd/zitadel/startup.yaml b/cmd/zitadel/startup.yaml new file mode 100644 index 0000000000..265ad49080 --- /dev/null +++ b/cmd/zitadel/startup.yaml @@ -0,0 +1,44 @@ +Tracing: + Type: google + Config: + ProjectID: $TRACING_PROJECT_ID + MetricPrefix: ZITADEL-V1 + Fraction: 1 + +Log: + Level: debug + Formatter: text + +Mgmt: + API: + GRPC: + ServerPort: 60020 + GatewayPort: 60021 + SearchLimit: 100 + CustomHeaders: + - x-caos- + +Auth: + API: + GRPC: + ServerPort: 60050 + GatewayPort: 60051 + SearchLimit: 100 + CustomHeaders: + - x-caos- + +Login: + + +Admin: + API: + GRPC: + ServerPort: 60090 + GatewayPort: 60091 + SearchLimit: 100 + CustomHeaders: + - x-caos- + +Console: + Port: '9090' + StaticDir: '/app/console/dist' diff --git a/go.mod b/go.mod index 34c29cbd49..731d99ee77 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/Masterminds/sprig v2.22.0+incompatible github.com/aws/aws-sdk-go v1.29.16 // indirect github.com/caos/logging v0.0.0-20191210002624-b3260f690a6a + github.com/ghodss/yaml v1.0.0 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b github.com/golang/mock v1.4.3 github.com/golang/protobuf v1.3.5 @@ -34,5 +35,5 @@ require ( google.golang.org/api v0.20.0 // indirect google.golang.org/genproto v0.0.0-20200319113533-08878b785e9c // indirect google.golang.org/grpc v1.28.0 - gopkg.in/yaml.v2 v2.2.8 + gopkg.in/yaml.v2 v2.2.8 // indirect ) diff --git a/internal/admin/config.go b/internal/admin/config.go new file mode 100644 index 0000000000..ddfb6fba44 --- /dev/null +++ b/internal/admin/config.go @@ -0,0 +1,4 @@ +package admin + +type Config struct { +} diff --git a/internal/api/grpc/config.go b/internal/api/grpc/config.go new file mode 100644 index 0000000000..4895fda7e1 --- /dev/null +++ b/internal/api/grpc/config.go @@ -0,0 +1,34 @@ +package grpc + +type Config struct { + ServerPort string + GatewayPort string + SearchLimit int + CustomHeaders []string +} + +func (c *Config) ToServerConfig() *ServerConfig { + return &ServerConfig{ + Port: c.ServerPort, + SearchLimit: c.SearchLimit, + } +} + +func (c *Config) ToGatewayConfig() *GatewayConfig { + return &GatewayConfig{ + Port: c.GatewayPort, + GRPCEndpoint: c.ServerPort, + CustomHeaders: c.CustomHeaders, + } +} + +type ServerConfig struct { + Port string + SearchLimit int +} + +type GatewayConfig struct { + Port string + GRPCEndpoint string + CustomHeaders []string +} diff --git a/internal/api/html/i18n.go b/internal/api/html/i18n.go index dd5d272668..17f1cb4e14 100644 --- a/internal/api/html/i18n.go +++ b/internal/api/html/i18n.go @@ -8,9 +8,9 @@ import ( "github.com/BurntSushi/toml" "github.com/caos/logging" + "github.com/ghodss/yaml" "github.com/nicksnyder/go-i18n/v2/i18n" "golang.org/x/text/language" - "gopkg.in/yaml.v2" "github.com/caos/zitadel/internal/api" http_util "github.com/caos/zitadel/internal/api/http" @@ -43,8 +43,9 @@ func NewTranslator(config TranslatorConfig) (*Translator, error) { func newBundle(i18nDir string, defaultLanguage language.Tag) (*i18n.Bundle, error) { bundle := i18n.NewBundle(defaultLanguage) - bundle.RegisterUnmarshalFunc("yaml", yaml.Unmarshal) - bundle.RegisterUnmarshalFunc("yml", yaml.Unmarshal) + yamlUnmarshal := func(data []byte, v interface{}) error { return yaml.Unmarshal(data, v) } + bundle.RegisterUnmarshalFunc("yaml", yamlUnmarshal) + bundle.RegisterUnmarshalFunc("yml", yamlUnmarshal) bundle.RegisterUnmarshalFunc("json", json.Unmarshal) bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal) files, err := ioutil.ReadDir(i18nDir) diff --git a/internal/auth/config.go b/internal/auth/config.go new file mode 100644 index 0000000000..bac255b177 --- /dev/null +++ b/internal/auth/config.go @@ -0,0 +1,4 @@ +package auth + +type Config struct { +} diff --git a/internal/config/config.go b/internal/config/config.go index 5740cd5f1d..7a385c5927 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -7,7 +7,7 @@ import ( "path/filepath" "github.com/BurntSushi/toml" - "gopkg.in/yaml.v2" + "github.com/ghodss/yaml" "github.com/caos/zitadel/internal/errors" ) @@ -21,7 +21,7 @@ type ReaderFunc func(data []byte, o interface{}) error var ( JSONReader = json.Unmarshal TOMLReader = toml.Unmarshal - YAMLReader = yaml.Unmarshal + YAMLReader = func(data []byte, o interface{}) error { return yaml.Unmarshal(data, o) } ) // Read deserializes each config file to the target obj diff --git a/internal/config/flag.go b/internal/config/flag.go new file mode 100644 index 0000000000..bb99d0a52c --- /dev/null +++ b/internal/config/flag.go @@ -0,0 +1,14 @@ +package config + +import "strings" + +type ArrayFlags []string + +func (i *ArrayFlags) String() string { + return strings.Join(*i, ";") +} + +func (i *ArrayFlags) Set(value string) error { + *i = append(*i, value) + return nil +} diff --git a/internal/login/config.go b/internal/login/config.go new file mode 100644 index 0000000000..7912985764 --- /dev/null +++ b/internal/login/config.go @@ -0,0 +1,4 @@ +package login + +type Config struct { +} diff --git a/internal/management/config.go b/internal/management/config.go new file mode 100644 index 0000000000..9b95a5228b --- /dev/null +++ b/internal/management/config.go @@ -0,0 +1,3 @@ +package management + +type Config struct{} diff --git a/pkg/admin/admin.go b/pkg/admin/admin.go index 681fd53646..968bb7fa75 100644 --- a/pkg/admin/admin.go +++ b/pkg/admin/admin.go @@ -3,12 +3,17 @@ package admin import ( "context" + app "github.com/caos/zitadel/internal/admin" + "github.com/caos/zitadel/internal/api/auth" "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/pkg/admin/api" ) type Config struct { + App *app.Config + API *api.Config } -func Start(ctx context.Context, config Config) error { +func Start(ctx context.Context, config *Config, authZ *auth.Config) error { return errors.ThrowUnimplemented(nil, "ADMIN-n8vw5", "not implemented yet") //TODO: implement } diff --git a/pkg/admin/api/config.go b/pkg/admin/api/config.go new file mode 100644 index 0000000000..b63086cc83 --- /dev/null +++ b/pkg/admin/api/config.go @@ -0,0 +1,7 @@ +package api + +import "github.com/caos/zitadel/internal/api/grpc" + +type Config struct { + GRPC *grpc.Config +} diff --git a/pkg/auth/api/config.go b/pkg/auth/api/config.go new file mode 100644 index 0000000000..b63086cc83 --- /dev/null +++ b/pkg/auth/api/config.go @@ -0,0 +1,7 @@ +package api + +import "github.com/caos/zitadel/internal/api/grpc" + +type Config struct { + GRPC *grpc.Config +} diff --git a/pkg/auth/auth.go b/pkg/auth/auth.go index 0ac10202a3..21f3229f67 100644 --- a/pkg/auth/auth.go +++ b/pkg/auth/auth.go @@ -3,12 +3,17 @@ package auth import ( "context" + "github.com/caos/zitadel/internal/api/auth" + app "github.com/caos/zitadel/internal/auth" "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/pkg/auth/api" ) type Config struct { + App *app.Config + API *api.Config } -func Start(ctx context.Context, config Config) error { +func Start(ctx context.Context, config *Config, authZ *auth.Config) error { return errors.ThrowUnimplemented(nil, "AUTH-l7Hdx", "not implemented yet") //TODO: implement } diff --git a/pkg/console/console.go b/pkg/console/console.go new file mode 100644 index 0000000000..8a17d33c2f --- /dev/null +++ b/pkg/console/console.go @@ -0,0 +1,16 @@ +package console + +import ( + "context" + + "github.com/caos/zitadel/internal/errors" +) + +type Config struct { + Port string + StaticDir string +} + +func Start(ctx context.Context, config *Config) error { + return errors.ThrowUnimplemented(nil, "CONSO-4cT5D", "not implemented yet") //TODO: implement +} diff --git a/pkg/login/api/config.go b/pkg/login/api/config.go new file mode 100644 index 0000000000..feed11d83a --- /dev/null +++ b/pkg/login/api/config.go @@ -0,0 +1,4 @@ +package api + +type Config struct { +} diff --git a/pkg/login/login.go b/pkg/login/login.go new file mode 100644 index 0000000000..8a593092a3 --- /dev/null +++ b/pkg/login/login.go @@ -0,0 +1,18 @@ +package login + +import ( + "context" + + "github.com/caos/zitadel/internal/errors" + app "github.com/caos/zitadel/internal/login" + "github.com/caos/zitadel/pkg/login/api" +) + +type Config struct { + App *app.Config + API *api.Config +} + +func Start(ctx context.Context, config *Config) error { + return errors.ThrowUnimplemented(nil, "LOGIN-3fwvD", "not implemented yet") //TODO: implement +} diff --git a/pkg/management/api/config.go b/pkg/management/api/config.go new file mode 100644 index 0000000000..b63086cc83 --- /dev/null +++ b/pkg/management/api/config.go @@ -0,0 +1,7 @@ +package api + +import "github.com/caos/zitadel/internal/api/grpc" + +type Config struct { + GRPC *grpc.Config +} diff --git a/pkg/management/management.go b/pkg/management/management.go index 23bf517569..2ba24ff227 100644 --- a/pkg/management/management.go +++ b/pkg/management/management.go @@ -3,12 +3,17 @@ package management import ( "context" + "github.com/caos/zitadel/internal/api/auth" "github.com/caos/zitadel/internal/errors" + app "github.com/caos/zitadel/internal/management" + "github.com/caos/zitadel/pkg/management/api" ) type Config struct { + App *app.Config + API *api.Config } -func Start(ctx context.Context, config Config) error { +func Start(ctx context.Context, config *Config, authZ *auth.Config) error { return errors.ThrowUnimplemented(nil, "MANAG-h3k3x", "not implemented yet") //TODO: implement } From 6bf96ecbd7640850a525999360f9a9385e8c5c38 Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Wed, 25 Mar 2020 09:32:52 +0100 Subject: [PATCH 19/39] add duration type --- internal/config/types/duration.go | 15 +++++++++ internal/config/types/duration_test.go | 46 ++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 internal/config/types/duration.go create mode 100644 internal/config/types/duration_test.go diff --git a/internal/config/types/duration.go b/internal/config/types/duration.go new file mode 100644 index 0000000000..6413aea835 --- /dev/null +++ b/internal/config/types/duration.go @@ -0,0 +1,15 @@ +package types + +import ( + "time" +) + +type Duration struct { + time.Duration +} + +func (d *Duration) UnmarshalText(data []byte) error { + var err error + d.Duration, err = time.ParseDuration(string(data)) + return err +} diff --git a/internal/config/types/duration_test.go b/internal/config/types/duration_test.go new file mode 100644 index 0000000000..8058d07a4d --- /dev/null +++ b/internal/config/types/duration_test.go @@ -0,0 +1,46 @@ +package types + +import ( + "testing" + "time" +) + +func TestDuration_UnmarshalText(t *testing.T) { + type args struct { + data []byte + } + tests := []struct { + name string + args args + wantErr bool + want time.Duration + }{ + { + "ok", + args{ + data: []byte("10s"), + }, + false, + time.Duration(10 * time.Second), + }, + { + "error", + args{ + data: []byte("10"), + }, + true, + time.Duration(0), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + d := &Duration{} + if err := d.UnmarshalText(tt.args.data); (err != nil) != tt.wantErr { + t.Errorf("UnmarshalText() error = %v, wantErr %v", err, tt.wantErr) + } + if d.Duration != tt.want { + t.Errorf("UnmarshalText() got = %v, want %v", d.Duration, tt.want) + } + }) + } +} From 1aaf721d92c4748f41df971a53d696f9aa98a2c3 Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Wed, 25 Mar 2020 10:41:17 +0100 Subject: [PATCH 20/39] cleanup --- cmd/zitadel/main.go | 5 ++--- cmd/zitadel/startup.yaml | 3 --- internal/api/auth/context.go | 4 ---- internal/api/grpc/config.go | 7 ++----- internal/config/{flag.go => array_flag.go} | 0 5 files changed, 4 insertions(+), 15 deletions(-) rename internal/config/{flag.go => array_flag.go} (100%) diff --git a/cmd/zitadel/main.go b/cmd/zitadel/main.go index 4c3137b9c6..e56940361d 100644 --- a/cmd/zitadel/main.go +++ b/cmd/zitadel/main.go @@ -22,8 +22,8 @@ type Config struct { Admin *admin.Config Console *console.Config - //Log - //Tracing tracing.TracingConfig + //Log //TODO: add + //Tracing tracing.TracingConfig //TODO: add AuthZ *authz.Config } @@ -35,7 +35,6 @@ func main() { loginEnabled := flag.Bool("login", true, "enable login ui") adminEnabled := flag.Bool("admin", true, "enable admin api") consoleEnabled := flag.Bool("console", true, "enable console ui") - flag.Parse() conf := new(Config) diff --git a/cmd/zitadel/startup.yaml b/cmd/zitadel/startup.yaml index 265ad49080..9a8a4bce69 100644 --- a/cmd/zitadel/startup.yaml +++ b/cmd/zitadel/startup.yaml @@ -14,7 +14,6 @@ Mgmt: GRPC: ServerPort: 60020 GatewayPort: 60021 - SearchLimit: 100 CustomHeaders: - x-caos- @@ -23,7 +22,6 @@ Auth: GRPC: ServerPort: 60050 GatewayPort: 60051 - SearchLimit: 100 CustomHeaders: - x-caos- @@ -35,7 +33,6 @@ Admin: GRPC: ServerPort: 60090 GatewayPort: 60091 - SearchLimit: 100 CustomHeaders: - x-caos- diff --git a/internal/api/auth/context.go b/internal/api/auth/context.go index 5638fa40d1..b17affec28 100644 --- a/internal/api/auth/context.go +++ b/internal/api/auth/context.go @@ -7,10 +7,6 @@ import ( "github.com/caos/logging" ) -const ( - HeaderOrgID = "x-caos-zitadel-orgid" -) - type CtxKeyPermissions struct{} type CtxKeyData struct{} diff --git a/internal/api/grpc/config.go b/internal/api/grpc/config.go index 4895fda7e1..1b3179d5a5 100644 --- a/internal/api/grpc/config.go +++ b/internal/api/grpc/config.go @@ -3,14 +3,12 @@ package grpc type Config struct { ServerPort string GatewayPort string - SearchLimit int CustomHeaders []string } func (c *Config) ToServerConfig() *ServerConfig { return &ServerConfig{ - Port: c.ServerPort, - SearchLimit: c.SearchLimit, + Port: c.ServerPort, } } @@ -23,8 +21,7 @@ func (c *Config) ToGatewayConfig() *GatewayConfig { } type ServerConfig struct { - Port string - SearchLimit int + Port string } type GatewayConfig struct { diff --git a/internal/config/flag.go b/internal/config/array_flag.go similarity index 100% rename from internal/config/flag.go rename to internal/config/array_flag.go From 5ba9b4c0969952a5ccc4f5ab6784afa556eba081 Mon Sep 17 00:00:00 2001 From: Florian Forster Date: Thu, 19 Mar 2020 15:19:18 +0100 Subject: [PATCH 21/39] docs(readme): initiate boilerplate (#18) * docs(readme): initiate boilerplate * Update README.md Co-Authored-By: livio-a Co-authored-by: livio-a --- README.md | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 546361b2d9..3ee954f4ab 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,28 @@ -# zitadel +# Zitadel -![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg) +[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release) ![Release Badge](https://github.com/caos/zitadel/workflows/Test,%20Build,%20Release/badge.svg) [![GitHub license](https://img.shields.io/github/license/caos/zitadel)](https://github.com/caos/zitadel/blob/master/LICENSE) -[![GitHub release](https://img.shields.io/github/release/caos/zitadel)](https://github.com/caos/zitadel/releases/) +[![GitHub release](https://img.shields.io/github/release/caos/zitadel)](https://gitHub.com/caos/zitadel/releases/) +> This project is in alpha state. The API will continue breaking until version 1.0.0 is released + +## What Is It + +It will be an IAM ;-) + +## How Does It Work + +## Why Another IAM + +## How To Use It + +## How To Contribute + +TBD + +## License + +See the exact licensing terms [here](./LICENSE) + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. From 9da20cfe25f9016c7d160ca0fc82eeee8d88e741 Mon Sep 17 00:00:00 2001 From: Florian Forster Date: Fri, 20 Mar 2020 06:30:10 +0100 Subject: [PATCH 22/39] docs(readme): security policy (#19) * Create SECURITY.md * Update README.md --- README.md | 4 ++++ SECURITY.md | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 SECURITY.md diff --git a/README.md b/README.md index 3ee954f4ab..eb9c8971e9 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,10 @@ It will be an IAM ;-) TBD +## Security + +See the policy [here](./SECURITY.md) + ## License See the exact licensing terms [here](./LICENSE) diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000000..3c2d48d751 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,43 @@ +# Security Policy + +At CAOS we are extremely grateful for security aware people that disclose vulnerabilities to us and the open source community. All reports will be investigated by our team. + +## Supported Versions + +After the initial Release the following version support will apply + +| Version | Supported | +| ------- | ------------------ | +| 1.x.x | :white_check_mark: (not yet available) | +| 0.x.x | :x: | + +## Reporting a vulnerability + +To file a incident, please disclose by email to security@caos.ch with the security details. + +At the moment GPG encryption is no yet supported, however you may sign your message at will. + +### When should I report a vulnerability + +* You think you discovered a ... + * ... potential security vulnerability in zitadel + * ... vulnerability in another project that zitadel bases on +* For projects with their own vulnerability reporting and disclosure process, please report it directly there + +### When should I NOT report a vulnerability + +* You need help applying security related updates +* Your issue is not security related + +## Security Vulnerability Response + +TBD + +## Public Disclosure + +All accepted and mitigated vulnerabilitys will be published on the [Github Security Page](https://github.com/caos/zitadel/security/advisories) + +### Timing + +We think it is crucial to publish advisories `ASAP` as mitigations are ready. But due to the unknown nature of the discloures the time frame can range from 7 to 90 days. + From b9833aa6048ada6b62dd4f0c828773115b099828 Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Wed, 25 Mar 2020 11:34:49 +0100 Subject: [PATCH 23/39] change ports --- cmd/zitadel/startup.yaml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/cmd/zitadel/startup.yaml b/cmd/zitadel/startup.yaml index 9a8a4bce69..c84f9015a1 100644 --- a/cmd/zitadel/startup.yaml +++ b/cmd/zitadel/startup.yaml @@ -12,30 +12,30 @@ Log: Mgmt: API: GRPC: - ServerPort: 60020 - GatewayPort: 60021 + ServerPort: 50010 + GatewayPort: 50011 CustomHeaders: - x-caos- Auth: API: GRPC: - ServerPort: 60050 - GatewayPort: 60051 + ServerPort: 50020 + GatewayPort: 50021 CustomHeaders: - x-caos- Login: - +# will get port range 5003x Admin: API: GRPC: - ServerPort: 60090 - GatewayPort: 60091 + ServerPort: 50040 + GatewayPort: 50041 CustomHeaders: - x-caos- Console: - Port: '9090' - StaticDir: '/app/console/dist' + Port: 50050 + StaticDir: /app/console/dist From eb1d22c6a3fc2b424aa8d0e7636698477aa4a58a Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Fri, 27 Mar 2020 13:44:50 +0100 Subject: [PATCH 24/39] clarify array_flag.go --- internal/config/array_flag.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/internal/config/array_flag.go b/internal/config/array_flag.go index bb99d0a52c..5a779545d0 100644 --- a/internal/config/array_flag.go +++ b/internal/config/array_flag.go @@ -1,7 +1,14 @@ package config -import "strings" +import ( + "flag" + "strings" +) +var _ flag.Value = (*ArrayFlags)(nil) + +//ArrayFlags implements the flag/Value interface +//allowing to set multiple string flags with the same name type ArrayFlags []string func (i *ArrayFlags) String() string { From f280da5a760972ea8ef9631be0d2008448552c97 Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Fri, 27 Mar 2020 13:45:08 +0100 Subject: [PATCH 25/39] remove empty lines --- internal/api/auth/authorization_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/internal/api/auth/authorization_test.go b/internal/api/auth/authorization_test.go index 5282e10c92..ac1193385e 100644 --- a/internal/api/auth/authorization_test.go +++ b/internal/api/auth/authorization_test.go @@ -210,7 +210,6 @@ func Test_GetFieldFromReq(t *testing.T) { } func Test_HasGlobalPermission(t *testing.T) { - type args struct { perms []string } @@ -245,7 +244,6 @@ func Test_HasGlobalPermission(t *testing.T) { } func Test_GetPermissionCtxIDs(t *testing.T) { - type args struct { perms []string } From f5af4461ad812bf3d4db2f83a84fdece000270e9 Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Fri, 27 Mar 2020 13:57:16 +0100 Subject: [PATCH 26/39] remove pointers on configs --- cmd/zitadel/main.go | 12 ++++++------ internal/api/grpc/config.go | 8 ++++---- pkg/admin/admin.go | 2 +- pkg/auth/auth.go | 2 +- pkg/console/console.go | 2 +- pkg/login/login.go | 6 +++--- pkg/management/api/config.go | 2 +- pkg/management/management.go | 6 +++--- 8 files changed, 20 insertions(+), 20 deletions(-) diff --git a/cmd/zitadel/main.go b/cmd/zitadel/main.go index e56940361d..5d0b1e6a9c 100644 --- a/cmd/zitadel/main.go +++ b/cmd/zitadel/main.go @@ -16,15 +16,15 @@ import ( ) type Config struct { - Mgmt *management.Config - Auth *auth.Config - Login *login.Config - Admin *admin.Config - Console *console.Config + Mgmt management.Config + Auth auth.Config + Login login.Config + Admin admin.Config + Console console.Config //Log //TODO: add //Tracing tracing.TracingConfig //TODO: add - AuthZ *authz.Config + AuthZ authz.Config } func main() { diff --git a/internal/api/grpc/config.go b/internal/api/grpc/config.go index 1b3179d5a5..03b743fdc1 100644 --- a/internal/api/grpc/config.go +++ b/internal/api/grpc/config.go @@ -6,14 +6,14 @@ type Config struct { CustomHeaders []string } -func (c *Config) ToServerConfig() *ServerConfig { - return &ServerConfig{ +func (c Config) ToServerConfig() ServerConfig { + return ServerConfig{ Port: c.ServerPort, } } -func (c *Config) ToGatewayConfig() *GatewayConfig { - return &GatewayConfig{ +func (c Config) ToGatewayConfig() GatewayConfig { + return GatewayConfig{ Port: c.GatewayPort, GRPCEndpoint: c.ServerPort, CustomHeaders: c.CustomHeaders, diff --git a/pkg/admin/admin.go b/pkg/admin/admin.go index 968bb7fa75..bdf9010253 100644 --- a/pkg/admin/admin.go +++ b/pkg/admin/admin.go @@ -14,6 +14,6 @@ type Config struct { API *api.Config } -func Start(ctx context.Context, config *Config, authZ *auth.Config) error { +func Start(ctx context.Context, config Config, authZ auth.Config) error { return errors.ThrowUnimplemented(nil, "ADMIN-n8vw5", "not implemented yet") //TODO: implement } diff --git a/pkg/auth/auth.go b/pkg/auth/auth.go index 21f3229f67..43527dc43b 100644 --- a/pkg/auth/auth.go +++ b/pkg/auth/auth.go @@ -14,6 +14,6 @@ type Config struct { API *api.Config } -func Start(ctx context.Context, config *Config, authZ *auth.Config) error { +func Start(ctx context.Context, config Config, authZ auth.Config) error { return errors.ThrowUnimplemented(nil, "AUTH-l7Hdx", "not implemented yet") //TODO: implement } diff --git a/pkg/console/console.go b/pkg/console/console.go index 8a17d33c2f..663a1197a7 100644 --- a/pkg/console/console.go +++ b/pkg/console/console.go @@ -11,6 +11,6 @@ type Config struct { StaticDir string } -func Start(ctx context.Context, config *Config) error { +func Start(ctx context.Context, config Config) error { return errors.ThrowUnimplemented(nil, "CONSO-4cT5D", "not implemented yet") //TODO: implement } diff --git a/pkg/login/login.go b/pkg/login/login.go index 8a593092a3..462ba37aa1 100644 --- a/pkg/login/login.go +++ b/pkg/login/login.go @@ -9,10 +9,10 @@ import ( ) type Config struct { - App *app.Config - API *api.Config + App app.Config + API api.Config } -func Start(ctx context.Context, config *Config) error { +func Start(ctx context.Context, config Config) error { return errors.ThrowUnimplemented(nil, "LOGIN-3fwvD", "not implemented yet") //TODO: implement } diff --git a/pkg/management/api/config.go b/pkg/management/api/config.go index b63086cc83..8fce0aca62 100644 --- a/pkg/management/api/config.go +++ b/pkg/management/api/config.go @@ -3,5 +3,5 @@ package api import "github.com/caos/zitadel/internal/api/grpc" type Config struct { - GRPC *grpc.Config + GRPC grpc.Config } diff --git a/pkg/management/management.go b/pkg/management/management.go index 2ba24ff227..9f6af48229 100644 --- a/pkg/management/management.go +++ b/pkg/management/management.go @@ -10,10 +10,10 @@ import ( ) type Config struct { - App *app.Config - API *api.Config + App app.Config + API api.Config } -func Start(ctx context.Context, config *Config, authZ *auth.Config) error { +func Start(ctx context.Context, config Config, authZ auth.Config) error { return errors.ThrowUnimplemented(nil, "MANAG-h3k3x", "not implemented yet") //TODO: implement } From b753e06f0b984a9a191ba3da79eeae9e99821665 Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Mon, 30 Mar 2020 07:04:21 +0200 Subject: [PATCH 27/39] improve some functions --- internal/api/html/i18n.go | 14 +++++++------- internal/api/html/renderer.go | 5 ++--- internal/api/http/cookie.go | 5 +---- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/internal/api/html/i18n.go b/internal/api/html/i18n.go index 17f1cb4e14..79b35ccc2e 100644 --- a/internal/api/html/i18n.go +++ b/internal/api/html/i18n.go @@ -98,12 +98,12 @@ func (t *Translator) localizer(langs ...string) *i18n.Localizer { func (t *Translator) langsFromRequest(r *http.Request) []string { langs := make([]string, 0) - if r != nil { - lang, err := t.cookieHandler.GetCookieValue(r, t.cookieName) - if err == nil { - langs = append(langs, lang) - } - langs = append(langs, r.Header.Get(api.AcceptLanguage)) + if r == nil { + return langs } - return langs + lang, err := t.cookieHandler.GetCookieValue(r, t.cookieName) + if err == nil { + langs = append(langs, lang) + } + return append(langs, r.Header.Get(api.AcceptLanguage)) } diff --git a/internal/api/html/renderer.go b/internal/api/html/renderer.go index 182087e31d..97a684263a 100644 --- a/internal/api/html/renderer.go +++ b/internal/api/html/renderer.go @@ -31,9 +31,8 @@ func NewRenderer(templatesDir string, tmplMapping map[string]string, funcs map[s func (r *Renderer) RenderTemplate(w http.ResponseWriter, req *http.Request, tmpl *template.Template, data interface{}, reqFuncs map[string]interface{}) { reqFuncs = r.registerTranslateFn(req, reqFuncs) - if err := tmpl.Funcs(reqFuncs).Execute(w, data); err != nil { - logging.Log("HTML-lF8F6w").WithError(err).WithField("template", tmpl.Name).Error("error rendering template") - } + err := tmpl.Funcs(reqFuncs).Execute(w, data) + logging.LogWithFields("HTML-lF8F6w", "template", tmpl.Name).OnError(err).Error("error rendering template") } func (r *Renderer) Localize(id string, args map[string]interface{}) string { diff --git a/internal/api/http/cookie.go b/internal/api/http/cookie.go index a28791aafc..f2e28b5294 100644 --- a/internal/api/http/cookie.go +++ b/internal/api/http/cookie.go @@ -85,10 +85,7 @@ func (c *CookieHandler) GetEncryptedCookieValue(r *http.Request, name string, va if c.securecookie == nil { return errors.ThrowInternal(nil, "HTTP-X6XpnL", "securecookie not configured") } - if err := c.securecookie.Decode(name, cookie.Value, value); err != nil { - return err - } - return nil + return c.securecookie.Decode(name, cookie.Value, value) } func (c *CookieHandler) SetCookie(w http.ResponseWriter, name string, value string) { From fa750a506829774a4418e6c78b89f92f37815af2 Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Mon, 30 Mar 2020 07:23:43 +0200 Subject: [PATCH 28/39] improve some functions --- internal/proto/struct.go | 7 +------ internal/tracing/caller.go | 10 ++++------ internal/tracing/config/config.go | 12 +++++------- internal/tracing/google/config.go | 5 ++--- internal/tracing/span.go | 4 +++- pkg/admin/admin.go | 4 ++-- pkg/admin/api/config.go | 2 +- pkg/auth/api/config.go | 2 +- pkg/auth/auth.go | 4 ++-- 9 files changed, 21 insertions(+), 29 deletions(-) diff --git a/internal/proto/struct.go b/internal/proto/struct.go index 24a6ce0e36..f1b5eb29f9 100644 --- a/internal/proto/struct.go +++ b/internal/proto/struct.go @@ -13,7 +13,6 @@ import ( func MustToPBStruct(object interface{}) *pb_struct.Struct { s, err := ToPBStruct(object) logging.Log("PROTO-7Aa3t").OnError(err).Panic("unable to map object to pb-struct") - return s } @@ -24,15 +23,12 @@ func BytesToPBStruct(b []byte) (*pb_struct.Struct, error) { } func ToPBStruct(object interface{}) (*pb_struct.Struct, error) { - fields := new(pb_struct.Struct) - marshalled, err := json.Marshal(object) if err != nil { return nil, err } - + fields := new(pb_struct.Struct) err = jsonpb.Unmarshal(bytes.NewReader(marshalled), fields) - return fields, err } @@ -47,6 +43,5 @@ func FromPBStruct(object interface{}, s *pb_struct.Struct) error { if err != nil { return err } - return json.Unmarshal([]byte(jsonString), object) } diff --git a/internal/tracing/caller.go b/internal/tracing/caller.go index c5dfb9a319..c8ab9071b0 100644 --- a/internal/tracing/caller.go +++ b/internal/tracing/caller.go @@ -8,17 +8,15 @@ import ( func GetCaller() string { fpcs := make([]uintptr, 1) - n := runtime.Callers(3, fpcs) if n == 0 { - logging.Log("HELPE-rWjfC").Debug("no caller") + logging.Log("TRACE-rWjfC").Debug("no caller") + return "" } - caller := runtime.FuncForPC(fpcs[0] - 1) if caller == nil { - logging.Log("HELPE-25POw").Debug("caller was nil") + logging.Log("TRACE-25POw").Debug("caller was nil") + return "" } - - // Print the name of the function return caller.Name() } diff --git a/internal/tracing/config/config.go b/internal/tracing/config/config.go index e2310fbce3..3681ddf107 100644 --- a/internal/tracing/config/config.go +++ b/internal/tracing/config/config.go @@ -3,9 +3,7 @@ package config import ( "encoding/json" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - + "github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/tracing" tracing_g "github.com/caos/zitadel/internal/tracing/google" tracing_log "github.com/caos/zitadel/internal/tracing/log" @@ -28,7 +26,7 @@ func (c *TracingConfig) UnmarshalJSON(data []byte) error { } if err := json.Unmarshal(data, &rc); err != nil { - return status.Errorf(codes.Internal, "%v parse config: %v", "TRACE-vmjS", err) + return errors.ThrowInternal(err, "TRACE-vmjS", "error parsing config") } c.Type = rc.Type @@ -36,7 +34,7 @@ func (c *TracingConfig) UnmarshalJSON(data []byte) error { var err error c.Config, err = newTracingConfig(c.Type, rc.Config) if err != nil { - return status.Errorf(codes.Internal, "%v parse config: %v", "TRACE-Ws9E", err) + return err } return c.Config.NewTracer() @@ -45,7 +43,7 @@ func (c *TracingConfig) UnmarshalJSON(data []byte) error { func newTracingConfig(tracerType string, configData []byte) (tracing.Config, error) { t, ok := tracer[tracerType] if !ok { - return nil, status.Errorf(codes.Internal, "%v No config: %v", "TRACE-HMEJ", tracerType) + return nil, errors.ThrowInternalf(nil, "TRACE-HMEJ", "config type %s not supported", tracerType) } tracingConfig := t() @@ -54,7 +52,7 @@ func newTracingConfig(tracerType string, configData []byte) (tracing.Config, err } if err := json.Unmarshal(configData, tracingConfig); err != nil { - return nil, status.Errorf(codes.Internal, "%v Could not read conifg: %v", "TRACE-1tSS", err) + return nil, errors.ThrowInternal(err, "TRACE-1tSS", "Could not read config: %v") } return tracingConfig, nil diff --git a/internal/tracing/google/config.go b/internal/tracing/google/config.go index 92d93f61bd..64ee3223ba 100644 --- a/internal/tracing/google/config.go +++ b/internal/tracing/google/config.go @@ -2,9 +2,8 @@ package google import ( "go.opencensus.io/trace" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" + "github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/tracing" ) @@ -16,7 +15,7 @@ type Config struct { func (c *Config) NewTracer() error { if !envIsSet() { - return status.Error(codes.InvalidArgument, "env not properly set, GOOGLE_APPLICATION_CREDENTIALS is misconfigured or missing") + return errors.ThrowInvalidArgument(nil, "GOOGL-sdh3a", "env not properly set, GOOGLE_APPLICATION_CREDENTIALS is misconfigured or missing") } tracing.T = &Tracer{projectID: c.ProjectID, metricPrefix: c.MetricPrefix, sampler: trace.ProbabilitySampler(c.Fraction)} diff --git a/internal/tracing/span.go b/internal/tracing/span.go index d958cb4b52..1ad46ca0b1 100644 --- a/internal/tracing/span.go +++ b/internal/tracing/span.go @@ -7,6 +7,8 @@ import ( "go.opencensus.io/trace" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + + "github.com/caos/zitadel/internal/errors" ) type Span struct { @@ -80,7 +82,7 @@ func toTraceAttribute(key string, value interface{}) (attr trace.Attribute, err if valueInt, err := convertToInt64(value); err == nil { return trace.Int64Attribute(key, valueInt), nil } - return attr, status.Error(codes.InvalidArgument, "Attribute is not of type bool, string or int64") + return attr, errors.ThrowInternal(nil, "TRACE-jlq3s", "Attribute is not of type bool, string or int64") } func convertToInt64(value interface{}) (int64, error) { diff --git a/pkg/admin/admin.go b/pkg/admin/admin.go index bdf9010253..0a18a4b145 100644 --- a/pkg/admin/admin.go +++ b/pkg/admin/admin.go @@ -10,8 +10,8 @@ import ( ) type Config struct { - App *app.Config - API *api.Config + App app.Config + API api.Config } func Start(ctx context.Context, config Config, authZ auth.Config) error { diff --git a/pkg/admin/api/config.go b/pkg/admin/api/config.go index b63086cc83..8fce0aca62 100644 --- a/pkg/admin/api/config.go +++ b/pkg/admin/api/config.go @@ -3,5 +3,5 @@ package api import "github.com/caos/zitadel/internal/api/grpc" type Config struct { - GRPC *grpc.Config + GRPC grpc.Config } diff --git a/pkg/auth/api/config.go b/pkg/auth/api/config.go index b63086cc83..8fce0aca62 100644 --- a/pkg/auth/api/config.go +++ b/pkg/auth/api/config.go @@ -3,5 +3,5 @@ package api import "github.com/caos/zitadel/internal/api/grpc" type Config struct { - GRPC *grpc.Config + GRPC grpc.Config } diff --git a/pkg/auth/auth.go b/pkg/auth/auth.go index 43527dc43b..f8838f83c0 100644 --- a/pkg/auth/auth.go +++ b/pkg/auth/auth.go @@ -10,8 +10,8 @@ import ( ) type Config struct { - App *app.Config - API *api.Config + App app.Config + API api.Config } func Start(ctx context.Context, config Config, authZ auth.Config) error { From 59dc4dbe85485982e5123f70e843d1d95f1b1a18 Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Mon, 30 Mar 2020 09:28:00 +0200 Subject: [PATCH 29/39] improve some functions --- internal/api/auth/permissions_test.go | 7 +- internal/crypto/aes.go | 2 +- internal/crypto/bcrypt.go | 2 +- internal/crypto/code.go | 16 ++--- internal/crypto/code_test.go | 6 +- internal/crypto/crypto.go | 24 +++---- internal/crypto/crypto_mock.go | 98 +++++++++++++-------------- internal/crypto/crypto_test.go | 10 +-- 8 files changed, 81 insertions(+), 84 deletions(-) diff --git a/internal/api/auth/permissions_test.go b/internal/api/auth/permissions_test.go index 6d0857d792..83e5a7f784 100644 --- a/internal/api/auth/permissions_test.go +++ b/internal/api/auth/permissions_test.go @@ -74,10 +74,8 @@ func Test_GetUserMethodPermissions(t *testing.T) { }, }, wantErr: true, - errFunc: func(err error) bool { - return caos_errs.IsUnauthenticated(err) - }, - result: []string{"project.read"}, + errFunc: caos_errs.IsUnauthenticated, + result: []string{"project.read"}, }, { name: "No Grants", @@ -393,7 +391,6 @@ func Test_AddRoleContextIDToPerm(t *testing.T) { } func Test_ExistisPerm(t *testing.T) { - type args struct { existing []string perm string diff --git a/internal/crypto/aes.go b/internal/crypto/aes.go index 31d3e46847..0aca064941 100644 --- a/internal/crypto/aes.go +++ b/internal/crypto/aes.go @@ -10,7 +10,7 @@ import ( "github.com/caos/zitadel/internal/errors" ) -var _ EncryptionAlg = (*AESCrypto)(nil) +var _ EncryptionAlgorithm = (*AESCrypto)(nil) type AESCrypto struct { keys map[string]string diff --git a/internal/crypto/bcrypt.go b/internal/crypto/bcrypt.go index e7daffb27d..d9b172478f 100644 --- a/internal/crypto/bcrypt.go +++ b/internal/crypto/bcrypt.go @@ -4,7 +4,7 @@ import ( "golang.org/x/crypto/bcrypt" ) -var _ HashAlg = (*BCrypt)(nil) +var _ HashAlgorithm = (*BCrypt)(nil) type BCrypt struct { cost int diff --git a/internal/crypto/code.go b/internal/crypto/code.go index 0537710da6..8738aef074 100644 --- a/internal/crypto/code.go +++ b/internal/crypto/code.go @@ -24,7 +24,7 @@ type Generator interface { type EncryptionGenerator struct { length uint expiry time.Duration - alg EncryptionAlg + alg EncryptionAlgorithm runes []rune } @@ -44,7 +44,7 @@ func (g *EncryptionGenerator) Runes() []rune { return g.runes } -func NewEncryptionGenerator(length uint, expiry time.Duration, alg EncryptionAlg, runes []rune) *EncryptionGenerator { +func NewEncryptionGenerator(length uint, expiry time.Duration, alg EncryptionAlgorithm, runes []rune) *EncryptionGenerator { return &EncryptionGenerator{ length: length, expiry: expiry, @@ -56,7 +56,7 @@ func NewEncryptionGenerator(length uint, expiry time.Duration, alg EncryptionAlg type HashGenerator struct { length uint expiry time.Duration - alg HashAlg + alg HashAlgorithm runes []rune } @@ -76,7 +76,7 @@ func (g *HashGenerator) Runes() []rune { return g.runes } -func NewHashGenerator(length uint, expiry time.Duration, alg HashAlg, runes []rune) *HashGenerator { +func NewHashGenerator(length uint, expiry time.Duration, alg HashAlgorithm, runes []rune) *HashGenerator { return &HashGenerator{ length: length, expiry: expiry, @@ -106,9 +106,9 @@ func VerifyCode(creationDate time.Time, expiry time.Duration, cryptoCode *Crypto return errors.ThrowPreconditionFailed(nil, "CODE-QvUQ4P", "verification code is expired") } switch alg := g.Alg().(type) { - case EncryptionAlg: + case EncryptionAlgorithm: return verifyEncryptedCode(cryptoCode, verificationCode, alg) - case HashAlg: + case HashAlgorithm: return verifyHashedCode(cryptoCode, verificationCode, alg) } return errors.ThrowInvalidArgument(nil, "CODE-fW2gNa", "generator alg is not supported") @@ -136,7 +136,7 @@ func generateRandomString(length uint, chars []rune) (string, error) { return "", nil } -func verifyEncryptedCode(cryptoCode *CryptoValue, verificationCode string, alg EncryptionAlg) error { +func verifyEncryptedCode(cryptoCode *CryptoValue, verificationCode string, alg EncryptionAlgorithm) error { code, err := DecryptString(cryptoCode, alg) if err != nil { return err @@ -148,6 +148,6 @@ func verifyEncryptedCode(cryptoCode *CryptoValue, verificationCode string, alg E return nil } -func verifyHashedCode(cryptoCode *CryptoValue, verificationCode string, alg HashAlg) error { +func verifyHashedCode(cryptoCode *CryptoValue, verificationCode string, alg HashAlgorithm) error { return CompareHash(cryptoCode, []byte(verificationCode), alg) } diff --git a/internal/crypto/code_test.go b/internal/crypto/code_test.go index f7f55390e7..4f62f22898 100644 --- a/internal/crypto/code_test.go +++ b/internal/crypto/code_test.go @@ -9,7 +9,7 @@ import ( ) func Test_Encrypted_OK(t *testing.T) { - mCrypto := NewMockEncryptionAlg(gomock.NewController(t)) + mCrypto := NewMockEncryptionAlgorithm(gomock.NewController(t)) mCrypto.EXPECT().Algorithm().AnyTimes().Return("enc") mCrypto.EXPECT().EncryptionKeyID().AnyTimes().Return("id") mCrypto.EXPECT().DecryptionKeyIDs().AnyTimes().Return([]string{"id"}) @@ -35,7 +35,7 @@ func Test_Encrypted_OK(t *testing.T) { } func Test_Verify_Encrypted_OK(t *testing.T) { - mCrypto := NewMockEncryptionAlg(gomock.NewController(t)) + mCrypto := NewMockEncryptionAlgorithm(gomock.NewController(t)) mCrypto.EXPECT().Algorithm().AnyTimes().Return("enc") mCrypto.EXPECT().EncryptionKeyID().AnyTimes().Return("id") mCrypto.EXPECT().DecryptionKeyIDs().AnyTimes().Return([]string{"id"}) @@ -57,7 +57,7 @@ func Test_Verify_Encrypted_OK(t *testing.T) { assert.NoError(t, err) } func Test_Verify_Encrypted_Invalid_Err(t *testing.T) { - mCrypto := NewMockEncryptionAlg(gomock.NewController(t)) + mCrypto := NewMockEncryptionAlgorithm(gomock.NewController(t)) mCrypto.EXPECT().Algorithm().AnyTimes().Return("enc") mCrypto.EXPECT().EncryptionKeyID().AnyTimes().Return("id") mCrypto.EXPECT().DecryptionKeyIDs().AnyTimes().Return([]string{"id"}) diff --git a/internal/crypto/crypto.go b/internal/crypto/crypto.go index 38ee06577b..c1b46d69d5 100644 --- a/internal/crypto/crypto.go +++ b/internal/crypto/crypto.go @@ -13,7 +13,7 @@ type Crypto interface { Algorithm() string } -type EncryptionAlg interface { +type EncryptionAlgorithm interface { Crypto EncryptionKeyID() string DecryptionKeyIDs() []string @@ -22,7 +22,7 @@ type EncryptionAlg interface { DecryptString(hashed []byte, keyID string) (string, error) } -type HashAlg interface { +type HashAlgorithm interface { Crypto Hash(value []byte) ([]byte, error) CompareHash(hashed, comparer []byte) error @@ -39,15 +39,15 @@ type CryptoType int func Crypt(value []byte, c Crypto) (*CryptoValue, error) { switch alg := c.(type) { - case EncryptionAlg: + case EncryptionAlgorithm: return Encrypt(value, alg) - case HashAlg: + case HashAlgorithm: return Hash(value, alg) } return nil, errors.ThrowInternal(nil, "CRYPT-r4IaHZ", "algorithm not supported") } -func Encrypt(value []byte, alg EncryptionAlg) (*CryptoValue, error) { +func Encrypt(value []byte, alg EncryptionAlgorithm) (*CryptoValue, error) { encrypted, err := alg.Encrypt(value) if err != nil { return nil, errors.ThrowInternal(err, "CRYPT-qCD0JB", "error encrypting value") @@ -60,21 +60,21 @@ func Encrypt(value []byte, alg EncryptionAlg) (*CryptoValue, error) { }, nil } -func Decrypt(value *CryptoValue, alg EncryptionAlg) ([]byte, error) { - if err := checkEncAlg(value, alg); err != nil { +func Decrypt(value *CryptoValue, alg EncryptionAlgorithm) ([]byte, error) { + if err := checkEncryptionAlgorithm(value, alg); err != nil { return nil, err } return alg.Decrypt(value.Crypted, value.KeyID) } -func DecryptString(value *CryptoValue, alg EncryptionAlg) (string, error) { - if err := checkEncAlg(value, alg); err != nil { +func DecryptString(value *CryptoValue, alg EncryptionAlgorithm) (string, error) { + if err := checkEncryptionAlgorithm(value, alg); err != nil { return "", err } return alg.DecryptString(value.Crypted, value.KeyID) } -func checkEncAlg(value *CryptoValue, alg EncryptionAlg) error { +func checkEncryptionAlgorithm(value *CryptoValue, alg EncryptionAlgorithm) error { if value.Algorithm != alg.Algorithm() { return errors.ThrowInvalidArgument(nil, "CRYPT-Nx7XlT", "value was encrypted with a different key") } @@ -86,7 +86,7 @@ func checkEncAlg(value *CryptoValue, alg EncryptionAlg) error { return errors.ThrowInvalidArgument(nil, "CRYPT-Kq12vn", "value was encrypted with a different key") } -func Hash(value []byte, alg HashAlg) (*CryptoValue, error) { +func Hash(value []byte, alg HashAlgorithm) (*CryptoValue, error) { hashed, err := alg.Hash(value) if err != nil { return nil, errors.ThrowInternal(err, "CRYPT-rBVaJU", "error hashing value") @@ -98,6 +98,6 @@ func Hash(value []byte, alg HashAlg) (*CryptoValue, error) { }, nil } -func CompareHash(value *CryptoValue, comparer []byte, alg HashAlg) error { +func CompareHash(value *CryptoValue, comparer []byte, alg HashAlgorithm) error { return alg.CompareHash(value.Crypted, comparer) } diff --git a/internal/crypto/crypto_mock.go b/internal/crypto/crypto_mock.go index 3785c285ae..439db21969 100644 --- a/internal/crypto/crypto_mock.go +++ b/internal/crypto/crypto_mock.go @@ -46,31 +46,31 @@ func (mr *MockCryptoMockRecorder) Algorithm() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Algorithm", reflect.TypeOf((*MockCrypto)(nil).Algorithm)) } -// MockEncryptionAlg is a mock of EncryptionAlg interface -type MockEncryptionAlg struct { +// MockEncryptionAlgorithm is a mock of EncryptionAlgorithm interface +type MockEncryptionAlgorithm struct { ctrl *gomock.Controller - recorder *MockEncryptionAlgMockRecorder + recorder *MockEncryptionAlgorithmMockRecorder } -// MockEncryptionAlgMockRecorder is the mock recorder for MockEncryptionAlg -type MockEncryptionAlgMockRecorder struct { - mock *MockEncryptionAlg +// MockEncryptionAlgorithmMockRecorder is the mock recorder for MockEncryptionAlgorithm +type MockEncryptionAlgorithmMockRecorder struct { + mock *MockEncryptionAlgorithm } -// NewMockEncryptionAlg creates a new mock instance -func NewMockEncryptionAlg(ctrl *gomock.Controller) *MockEncryptionAlg { - mock := &MockEncryptionAlg{ctrl: ctrl} - mock.recorder = &MockEncryptionAlgMockRecorder{mock} +// NewMockEncryptionAlgorithm creates a new mock instance +func NewMockEncryptionAlgorithm(ctrl *gomock.Controller) *MockEncryptionAlgorithm { + mock := &MockEncryptionAlgorithm{ctrl: ctrl} + mock.recorder = &MockEncryptionAlgorithmMockRecorder{mock} return mock } // EXPECT returns an object that allows the caller to indicate expected use -func (m *MockEncryptionAlg) EXPECT() *MockEncryptionAlgMockRecorder { +func (m *MockEncryptionAlgorithm) EXPECT() *MockEncryptionAlgorithmMockRecorder { return m.recorder } // Algorithm mocks base method -func (m *MockEncryptionAlg) Algorithm() string { +func (m *MockEncryptionAlgorithm) Algorithm() string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Algorithm") ret0, _ := ret[0].(string) @@ -78,13 +78,13 @@ func (m *MockEncryptionAlg) Algorithm() string { } // Algorithm indicates an expected call of Algorithm -func (mr *MockEncryptionAlgMockRecorder) Algorithm() *gomock.Call { +func (mr *MockEncryptionAlgorithmMockRecorder) Algorithm() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Algorithm", reflect.TypeOf((*MockEncryptionAlg)(nil).Algorithm)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Algorithm", reflect.TypeOf((*MockEncryptionAlgorithm)(nil).Algorithm)) } // EncryptionKeyID mocks base method -func (m *MockEncryptionAlg) EncryptionKeyID() string { +func (m *MockEncryptionAlgorithm) EncryptionKeyID() string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EncryptionKeyID") ret0, _ := ret[0].(string) @@ -92,13 +92,13 @@ func (m *MockEncryptionAlg) EncryptionKeyID() string { } // EncryptionKeyID indicates an expected call of EncryptionKeyID -func (mr *MockEncryptionAlgMockRecorder) EncryptionKeyID() *gomock.Call { +func (mr *MockEncryptionAlgorithmMockRecorder) EncryptionKeyID() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EncryptionKeyID", reflect.TypeOf((*MockEncryptionAlg)(nil).EncryptionKeyID)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EncryptionKeyID", reflect.TypeOf((*MockEncryptionAlgorithm)(nil).EncryptionKeyID)) } // DecryptionKeyIDs mocks base method -func (m *MockEncryptionAlg) DecryptionKeyIDs() []string { +func (m *MockEncryptionAlgorithm) DecryptionKeyIDs() []string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "DecryptionKeyIDs") ret0, _ := ret[0].([]string) @@ -106,13 +106,13 @@ func (m *MockEncryptionAlg) DecryptionKeyIDs() []string { } // DecryptionKeyIDs indicates an expected call of DecryptionKeyIDs -func (mr *MockEncryptionAlgMockRecorder) DecryptionKeyIDs() *gomock.Call { +func (mr *MockEncryptionAlgorithmMockRecorder) DecryptionKeyIDs() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DecryptionKeyIDs", reflect.TypeOf((*MockEncryptionAlg)(nil).DecryptionKeyIDs)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DecryptionKeyIDs", reflect.TypeOf((*MockEncryptionAlgorithm)(nil).DecryptionKeyIDs)) } // Encrypt mocks base method -func (m *MockEncryptionAlg) Encrypt(value []byte) ([]byte, error) { +func (m *MockEncryptionAlgorithm) Encrypt(value []byte) ([]byte, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Encrypt", value) ret0, _ := ret[0].([]byte) @@ -121,13 +121,13 @@ func (m *MockEncryptionAlg) Encrypt(value []byte) ([]byte, error) { } // Encrypt indicates an expected call of Encrypt -func (mr *MockEncryptionAlgMockRecorder) Encrypt(value interface{}) *gomock.Call { +func (mr *MockEncryptionAlgorithmMockRecorder) Encrypt(value interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Encrypt", reflect.TypeOf((*MockEncryptionAlg)(nil).Encrypt), value) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Encrypt", reflect.TypeOf((*MockEncryptionAlgorithm)(nil).Encrypt), value) } // Decrypt mocks base method -func (m *MockEncryptionAlg) Decrypt(hashed []byte, keyID string) ([]byte, error) { +func (m *MockEncryptionAlgorithm) Decrypt(hashed []byte, keyID string) ([]byte, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Decrypt", hashed, keyID) ret0, _ := ret[0].([]byte) @@ -136,13 +136,13 @@ func (m *MockEncryptionAlg) Decrypt(hashed []byte, keyID string) ([]byte, error) } // Decrypt indicates an expected call of Decrypt -func (mr *MockEncryptionAlgMockRecorder) Decrypt(hashed, keyID interface{}) *gomock.Call { +func (mr *MockEncryptionAlgorithmMockRecorder) Decrypt(hashed, keyID interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Decrypt", reflect.TypeOf((*MockEncryptionAlg)(nil).Decrypt), hashed, keyID) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Decrypt", reflect.TypeOf((*MockEncryptionAlgorithm)(nil).Decrypt), hashed, keyID) } // DecryptString mocks base method -func (m *MockEncryptionAlg) DecryptString(hashed []byte, keyID string) (string, error) { +func (m *MockEncryptionAlgorithm) DecryptString(hashed []byte, keyID string) (string, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "DecryptString", hashed, keyID) ret0, _ := ret[0].(string) @@ -151,36 +151,36 @@ func (m *MockEncryptionAlg) DecryptString(hashed []byte, keyID string) (string, } // DecryptString indicates an expected call of DecryptString -func (mr *MockEncryptionAlgMockRecorder) DecryptString(hashed, keyID interface{}) *gomock.Call { +func (mr *MockEncryptionAlgorithmMockRecorder) DecryptString(hashed, keyID interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DecryptString", reflect.TypeOf((*MockEncryptionAlg)(nil).DecryptString), hashed, keyID) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DecryptString", reflect.TypeOf((*MockEncryptionAlgorithm)(nil).DecryptString), hashed, keyID) } -// MockHashAlg is a mock of HashAlg interface -type MockHashAlg struct { +// MockHashAlgorithm is a mock of HashAlgorithm interface +type MockHashAlgorithm struct { ctrl *gomock.Controller - recorder *MockHashAlgMockRecorder + recorder *MockHashAlgorithmMockRecorder } -// MockHashAlgMockRecorder is the mock recorder for MockHashAlg -type MockHashAlgMockRecorder struct { - mock *MockHashAlg +// MockHashAlgorithmMockRecorder is the mock recorder for MockHashAlgorithm +type MockHashAlgorithmMockRecorder struct { + mock *MockHashAlgorithm } -// NewMockHashAlg creates a new mock instance -func NewMockHashAlg(ctrl *gomock.Controller) *MockHashAlg { - mock := &MockHashAlg{ctrl: ctrl} - mock.recorder = &MockHashAlgMockRecorder{mock} +// NewMockHashAlgorithm creates a new mock instance +func NewMockHashAlgorithm(ctrl *gomock.Controller) *MockHashAlgorithm { + mock := &MockHashAlgorithm{ctrl: ctrl} + mock.recorder = &MockHashAlgorithmMockRecorder{mock} return mock } // EXPECT returns an object that allows the caller to indicate expected use -func (m *MockHashAlg) EXPECT() *MockHashAlgMockRecorder { +func (m *MockHashAlgorithm) EXPECT() *MockHashAlgorithmMockRecorder { return m.recorder } // Algorithm mocks base method -func (m *MockHashAlg) Algorithm() string { +func (m *MockHashAlgorithm) Algorithm() string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Algorithm") ret0, _ := ret[0].(string) @@ -188,13 +188,13 @@ func (m *MockHashAlg) Algorithm() string { } // Algorithm indicates an expected call of Algorithm -func (mr *MockHashAlgMockRecorder) Algorithm() *gomock.Call { +func (mr *MockHashAlgorithmMockRecorder) Algorithm() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Algorithm", reflect.TypeOf((*MockHashAlg)(nil).Algorithm)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Algorithm", reflect.TypeOf((*MockHashAlgorithm)(nil).Algorithm)) } // Hash mocks base method -func (m *MockHashAlg) Hash(value []byte) ([]byte, error) { +func (m *MockHashAlgorithm) Hash(value []byte) ([]byte, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Hash", value) ret0, _ := ret[0].([]byte) @@ -203,13 +203,13 @@ func (m *MockHashAlg) Hash(value []byte) ([]byte, error) { } // Hash indicates an expected call of Hash -func (mr *MockHashAlgMockRecorder) Hash(value interface{}) *gomock.Call { +func (mr *MockHashAlgorithmMockRecorder) Hash(value interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Hash", reflect.TypeOf((*MockHashAlg)(nil).Hash), value) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Hash", reflect.TypeOf((*MockHashAlgorithm)(nil).Hash), value) } // CompareHash mocks base method -func (m *MockHashAlg) CompareHash(hashed, comparer []byte) error { +func (m *MockHashAlgorithm) CompareHash(hashed, comparer []byte) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CompareHash", hashed, comparer) ret0, _ := ret[0].(error) @@ -217,7 +217,7 @@ func (m *MockHashAlg) CompareHash(hashed, comparer []byte) error { } // CompareHash indicates an expected call of CompareHash -func (mr *MockHashAlgMockRecorder) CompareHash(hashed, comparer interface{}) *gomock.Call { +func (mr *MockHashAlgorithmMockRecorder) CompareHash(hashed, comparer interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CompareHash", reflect.TypeOf((*MockHashAlg)(nil).CompareHash), hashed, comparer) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CompareHash", reflect.TypeOf((*MockHashAlgorithm)(nil).CompareHash), hashed, comparer) } diff --git a/internal/crypto/crypto_test.go b/internal/crypto/crypto_test.go index 76334884b9..fa5c4a5194 100644 --- a/internal/crypto/crypto_test.go +++ b/internal/crypto/crypto_test.go @@ -104,7 +104,7 @@ func TestCrypt(t *testing.T) { func TestEncrypt(t *testing.T) { type args struct { value []byte - c EncryptionAlg + c EncryptionAlgorithm } tests := []struct { name string @@ -136,7 +136,7 @@ func TestEncrypt(t *testing.T) { func TestDecrypt(t *testing.T) { type args struct { value *CryptoValue - c EncryptionAlg + c EncryptionAlgorithm } tests := []struct { name string @@ -174,7 +174,7 @@ func TestDecrypt(t *testing.T) { func TestDecryptString(t *testing.T) { type args struct { value *CryptoValue - c EncryptionAlg + c EncryptionAlgorithm } tests := []struct { name string @@ -212,7 +212,7 @@ func TestDecryptString(t *testing.T) { func TestHash(t *testing.T) { type args struct { value []byte - c HashAlg + c HashAlgorithm } tests := []struct { name string @@ -245,7 +245,7 @@ func TestCompareHash(t *testing.T) { type args struct { value *CryptoValue comparer []byte - c HashAlg + c HashAlgorithm } tests := []struct { name string From 501d45382224a06deac734d15fca1819a67ead4e Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Mon, 30 Mar 2020 09:58:55 +0200 Subject: [PATCH 30/39] remove x-grpc-web header in cors --- internal/api/http/middleware/cors_interceptor.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/api/http/middleware/cors_interceptor.go b/internal/api/http/middleware/cors_interceptor.go index 6fd154b469..379fbc38b7 100644 --- a/internal/api/http/middleware/cors_interceptor.go +++ b/internal/api/http/middleware/cors_interceptor.go @@ -18,7 +18,6 @@ var ( api.AcceptLanguage, api.Authorization, api.ZitadelOrgID, - "x-grpc-web", //TODO: needed }, AllowedMethods: []string{ http.MethodOptions, From e5e39b3a6a54e0e9a92ad9dddcf482a3c96b7784 Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Mon, 30 Mar 2020 10:06:48 +0200 Subject: [PATCH 31/39] remove pointer on ctxData --- internal/api/auth/context.go | 20 +++++--------------- internal/api/auth/permissions_test.go | 2 +- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/internal/api/auth/context.go b/internal/api/auth/context.go index b17affec28..78ef0bc252 100644 --- a/internal/api/auth/context.go +++ b/internal/api/auth/context.go @@ -2,7 +2,6 @@ package auth import ( "context" - "time" "github.com/caos/logging" ) @@ -43,24 +42,15 @@ func VerifyTokenAndWriteCtxData(ctx context.Context, token, orgID string, t Toke projectID, err := t.GetProjectIDByClientID(ctx, clientID) logging.LogWithFields("AUTH-GfAoV", "clientID", clientID).OnError(err).Warn("could not read projectid by clientid") - return context.WithValue(ctx, CtxKeyData{}, &CtxData{UserID: userID, OrgID: orgID, ProjectID: projectID, AgentID: agentID}), nil + return context.WithValue(ctx, CtxKeyData{}, CtxData{UserID: userID, OrgID: orgID, ProjectID: projectID, AgentID: agentID}), nil } func GetCtxData(ctx context.Context) CtxData { - if data := ctx.Value(CtxKeyData{}); data != nil { - ctxData, ok := data.(*CtxData) - if ok { - return *ctxData - } - time.Now() - } - return CtxData{} + ctxData, _ := ctx.Value(CtxKeyData{}).(CtxData) + return ctxData } func GetPermissionsFromCtx(ctx context.Context) []string { - if data := ctx.Value(CtxKeyPermissions{}); data != nil { - ctxPermission, _ := data.([]string) - return ctxPermission - } - return nil + ctxPermission, _ := ctx.Value(CtxKeyPermissions{}).([]string) + return ctxPermission } diff --git a/internal/api/auth/permissions_test.go b/internal/api/auth/permissions_test.go index 83e5a7f784..0a433f43c6 100644 --- a/internal/api/auth/permissions_test.go +++ b/internal/api/auth/permissions_test.go @@ -8,7 +8,7 @@ import ( ) func getTestCtx(userID, orgID string) context.Context { - return context.WithValue(context.Background(), CtxKeyData{}, &CtxData{UserID: userID, OrgID: orgID}) + return context.WithValue(context.Background(), CtxKeyData{}, CtxData{UserID: userID, OrgID: orgID}) } type testVerifier struct { From 106a6ec1435a59f3e3df29a1c9f701f587e68df5 Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Mon, 30 Mar 2020 10:09:38 +0200 Subject: [PATCH 32/39] fix test --- internal/api/auth/permissions_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/api/auth/permissions_test.go b/internal/api/auth/permissions_test.go index 0a433f43c6..d2afc36dfc 100644 --- a/internal/api/auth/permissions_test.go +++ b/internal/api/auth/permissions_test.go @@ -27,7 +27,7 @@ func (v *testVerifier) GetProjectIDByClientID(ctx context.Context, clientID stri return "", nil } -func EqualStringArray(a, b []string) bool { +func equalStringArray(a, b []string) bool { if len(a) != len(b) { return false } @@ -133,7 +133,7 @@ func Test_GetUserMethodPermissions(t *testing.T) { t.Errorf("got wrong err: %v ", err) } - if !tt.wantErr && !EqualStringArray(perms, tt.result) { + if !tt.wantErr && !equalStringArray(perms, tt.result) { t.Errorf("got wrong result, expecting: %v, actual: %v ", tt.result, perms) } }) @@ -239,7 +239,7 @@ func Test_MapGrantsToPermissions(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := mapGrantsToPermissions(tt.args.requiredPerm, tt.args.grants, tt.args.authConfig) - if !EqualStringArray(result, tt.result) { + if !equalStringArray(result, tt.result) { t.Errorf("got wrong result, expecting: %v, actual: %v ", tt.result, result) } }) @@ -346,7 +346,7 @@ func Test_MapRoleToPerm(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := mapRoleToPerm(tt.args.requiredPerm, tt.args.actualRole, tt.args.authConfig, tt.args.resolvedPermissions) - if !EqualStringArray(result, tt.result) { + if !equalStringArray(result, tt.result) { t.Errorf("got wrong result, expecting: %v, actual: %v ", tt.result, result) } }) From e04c0116f5e5c9d5ef53b83d43d862fddcb19d4a Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Mon, 30 Mar 2020 11:26:02 +0200 Subject: [PATCH 33/39] refactor crypto tests --- internal/crypto/code.go | 6 + internal/crypto/code_test.go | 376 +++++++++++++++++++++++++++++------ internal/crypto/crypto.go | 3 + internal/crypto/generate.go | 1 + 4 files changed, 328 insertions(+), 58 deletions(-) diff --git a/internal/crypto/code.go b/internal/crypto/code.go index 8738aef074..7cff29a746 100644 --- a/internal/crypto/code.go +++ b/internal/crypto/code.go @@ -137,6 +137,9 @@ func generateRandomString(length uint, chars []rune) (string, error) { } func verifyEncryptedCode(cryptoCode *CryptoValue, verificationCode string, alg EncryptionAlgorithm) error { + if cryptoCode == nil { + return errors.ThrowInvalidArgument(nil, "CRYPT-aqrFV", "cryptoCode must not be nil") + } code, err := DecryptString(cryptoCode, alg) if err != nil { return err @@ -149,5 +152,8 @@ func verifyEncryptedCode(cryptoCode *CryptoValue, verificationCode string, alg E } func verifyHashedCode(cryptoCode *CryptoValue, verificationCode string, alg HashAlgorithm) error { + if cryptoCode == nil { + return errors.ThrowInvalidArgument(nil, "CRYPT-2q3r", "cryptoCode must not be nil") + } return CompareHash(cryptoCode, []byte(verificationCode), alg) } diff --git a/internal/crypto/code_test.go b/internal/crypto/code_test.go index 4f62f22898..8e1947c2d8 100644 --- a/internal/crypto/code_test.go +++ b/internal/crypto/code_test.go @@ -5,10 +5,11 @@ import ( "time" "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" + + "github.com/caos/zitadel/internal/errors" ) -func Test_Encrypted_OK(t *testing.T) { +func createMockEncryptionAlg(t *testing.T) EncryptionAlgorithm { mCrypto := NewMockEncryptionAlgorithm(gomock.NewController(t)) mCrypto.EXPECT().Algorithm().AnyTimes().Return("enc") mCrypto.EXPECT().EncryptionKeyID().AnyTimes().Return("id") @@ -19,74 +20,333 @@ func Test_Encrypted_OK(t *testing.T) { }, ) mCrypto.EXPECT().DecryptString(gomock.Any(), gomock.Any()).DoAndReturn( - func(code []byte, _ string) (string, error) { + func(code []byte, keyID string) (string, error) { + if keyID != "id" { + return "", errors.ThrowInternal(nil, "id", "invalid key id") + } return string(code), nil }, ) - generator := NewEncryptionGenerator(6, 0, mCrypto, Digits) - - crypto, code, err := NewCode(generator) - assert.NoError(t, err) - - decrypted, err := DecryptString(crypto, generator.alg) - assert.NoError(t, err) - assert.Equal(t, code, decrypted) - assert.Equal(t, 6, len(decrypted)) + return mCrypto } -func Test_Verify_Encrypted_OK(t *testing.T) { - mCrypto := NewMockEncryptionAlgorithm(gomock.NewController(t)) - mCrypto.EXPECT().Algorithm().AnyTimes().Return("enc") - mCrypto.EXPECT().EncryptionKeyID().AnyTimes().Return("id") - mCrypto.EXPECT().DecryptionKeyIDs().AnyTimes().Return([]string{"id"}) - mCrypto.EXPECT().DecryptString(gomock.Any(), gomock.Any()).DoAndReturn( - func(code []byte, _ string) (string, error) { - return string(code), nil +func createMockHashAlg(t *testing.T) HashAlgorithm { + mCrypto := NewMockHashAlgorithm(gomock.NewController(t)) + mCrypto.EXPECT().Algorithm().AnyTimes().Return("hash") + mCrypto.EXPECT().Hash(gomock.Any()).DoAndReturn( + func(code []byte) ([]byte, error) { + return code, nil }, ) - creationDate := time.Now() - code := &CryptoValue{ - CryptoType: TypeEncryption, - Algorithm: "enc", - KeyID: "id", - Crypted: []byte("code"), + mCrypto.EXPECT().CompareHash(gomock.Any(), gomock.Any()).DoAndReturn( + func(hashed, comparer []byte) error { + if string(hashed) != string(comparer) { + return errors.ThrowInternal(nil, "id", "invalid") + } + return nil + }, + ) + return mCrypto +} + +func createMockCrypto(t *testing.T) Crypto { + mCrypto := NewMockCrypto(gomock.NewController(t)) + mCrypto.EXPECT().Algorithm().AnyTimes().Return("crypto") + return mCrypto +} + +func createMockGenerator(t *testing.T, crypto Crypto) Generator { + mGenerator := NewMockGenerator(gomock.NewController(t)) + mGenerator.EXPECT().Alg().AnyTimes().Return(crypto) + return mGenerator +} + +func TestIsCodeExpired(t *testing.T) { + type args struct { + creationDate time.Time + expiry time.Duration } - generator := NewEncryptionGenerator(6, 0, mCrypto, Digits) - - err := VerifyCode(creationDate, 1*time.Hour, code, "code", generator) - assert.NoError(t, err) -} -func Test_Verify_Encrypted_Invalid_Err(t *testing.T) { - mCrypto := NewMockEncryptionAlgorithm(gomock.NewController(t)) - mCrypto.EXPECT().Algorithm().AnyTimes().Return("enc") - mCrypto.EXPECT().EncryptionKeyID().AnyTimes().Return("id") - mCrypto.EXPECT().DecryptionKeyIDs().AnyTimes().Return([]string{"id"}) - mCrypto.EXPECT().DecryptString(gomock.Any(), gomock.Any()).DoAndReturn( - func(code []byte, _ string) (string, error) { - return string(code), nil + tests := []struct { + name string + args args + want bool + }{ + { + "not expired", + args{ + creationDate: time.Now(), + expiry: time.Duration(5 * time.Minute), + }, + false, + }, + { + "expired", + args{ + creationDate: time.Now().Add(-5 * time.Minute), + expiry: time.Duration(5 * time.Minute), + }, + true, }, - ) - creationDate := time.Now() - code := &CryptoValue{ - CryptoType: TypeEncryption, - Algorithm: "enc", - KeyID: "id", - Crypted: []byte("code"), } - generator := NewEncryptionGenerator(6, 0, mCrypto, Digits) - - err := VerifyCode(creationDate, 1*time.Hour, code, "wrong", generator) - assert.Error(t, err) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := IsCodeExpired(tt.args.creationDate, tt.args.expiry); got != tt.want { + t.Errorf("IsCodeExpired() = %v, want %v", got, tt.want) + } + }) + } } -func TestIsCodeExpired_Expired(t *testing.T) { - creationDate := time.Date(2019, time.April, 1, 0, 0, 0, 0, time.UTC) - expired := IsCodeExpired(creationDate, 1*time.Hour) - assert.True(t, expired) +func TestVerifyCode(t *testing.T) { + type args struct { + creationDate time.Time + expiry time.Duration + cryptoCode *CryptoValue + verificationCode string + g Generator + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + "expired", + args{ + creationDate: time.Now().Add(-5 * time.Minute), + expiry: 5 * time.Minute, + cryptoCode: nil, + verificationCode: "", + g: nil, + }, + true, + }, + { + "unsupported alg err", + args{ + creationDate: time.Now(), + expiry: 5 * time.Minute, + cryptoCode: nil, + verificationCode: "code", + g: createMockGenerator(t, createMockCrypto(t)), + }, + true, + }, + { + "encryption alg ok", + args{ + creationDate: time.Now(), + expiry: 5 * time.Minute, + cryptoCode: &CryptoValue{ + CryptoType: TypeEncryption, + Algorithm: "enc", + KeyID: "id", + Crypted: []byte("code"), + }, + verificationCode: "code", + g: createMockGenerator(t, createMockEncryptionAlg(t)), + }, + false, + }, + { + "hash alg ok", + args{ + creationDate: time.Now(), + expiry: 5 * time.Minute, + cryptoCode: &CryptoValue{ + CryptoType: TypeHash, + Algorithm: "hash", + Crypted: []byte("code"), + }, + verificationCode: "code", + g: createMockGenerator(t, createMockHashAlg(t)), + }, + false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := VerifyCode(tt.args.creationDate, tt.args.expiry, tt.args.cryptoCode, tt.args.verificationCode, tt.args.g); (err != nil) != tt.wantErr { + t.Errorf("VerifyCode() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } } -func TestIsCodeExpired_NotExpired(t *testing.T) { - creationDate := time.Now() - expired := IsCodeExpired(creationDate, 1*time.Hour) - assert.False(t, expired) +func Test_verifyEncryptedCode(t *testing.T) { + type args struct { + cryptoCode *CryptoValue + verificationCode string + alg EncryptionAlgorithm + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + "nil error", + args{ + cryptoCode: nil, + verificationCode: "", + alg: createMockEncryptionAlg(t), + }, + true, + }, + { + "wrong cryptotype error", + args{ + cryptoCode: &CryptoValue{ + CryptoType: TypeHash, + Crypted: nil, + }, + verificationCode: "", + alg: createMockEncryptionAlg(t), + }, + true, + }, + { + "wrong algorithm error", + args{ + cryptoCode: &CryptoValue{ + CryptoType: TypeEncryption, + Algorithm: "enc2", + Crypted: nil, + }, + verificationCode: "", + alg: createMockEncryptionAlg(t), + }, + true, + }, + { + "wrong key id error", + args{ + cryptoCode: &CryptoValue{ + CryptoType: TypeEncryption, + Algorithm: "enc", + Crypted: nil, + }, + verificationCode: "wrong", + alg: createMockEncryptionAlg(t), + }, + true, + }, + { + "wrong verification code error", + args{ + cryptoCode: &CryptoValue{ + CryptoType: TypeEncryption, + Algorithm: "enc", + KeyID: "id", + Crypted: []byte("code"), + }, + verificationCode: "wrong", + alg: createMockEncryptionAlg(t), + }, + true, + }, + { + "verification code ok", + args{ + cryptoCode: &CryptoValue{ + CryptoType: TypeEncryption, + Algorithm: "enc", + KeyID: "id", + Crypted: []byte("code"), + }, + verificationCode: "code", + alg: createMockEncryptionAlg(t), + }, + false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := verifyEncryptedCode(tt.args.cryptoCode, tt.args.verificationCode, tt.args.alg); (err != nil) != tt.wantErr { + t.Errorf("verifyEncryptedCode() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func Test_verifyHashedCode(t *testing.T) { + type args struct { + cryptoCode *CryptoValue + verificationCode string + alg HashAlgorithm + } + tests := []struct { + name string + args args + wantErr bool + }{ + + { + "nil error", + args{ + cryptoCode: nil, + verificationCode: "", + alg: createMockHashAlg(t), + }, + true, + }, + { + "wrong cryptotype error", + args{ + cryptoCode: &CryptoValue{ + CryptoType: TypeEncryption, + Crypted: nil, + }, + verificationCode: "", + alg: createMockHashAlg(t), + }, + true, + }, + { + "wrong algorithm error", + args{ + cryptoCode: &CryptoValue{ + CryptoType: TypeHash, + Algorithm: "hash2", + Crypted: nil, + }, + verificationCode: "", + alg: createMockHashAlg(t), + }, + true, + }, + { + "wrong verification code error", + args{ + cryptoCode: &CryptoValue{ + CryptoType: TypeHash, + Algorithm: "hash", + Crypted: []byte("code"), + }, + verificationCode: "wrong", + alg: createMockHashAlg(t), + }, + true, + }, + { + "verification code ok", + args{ + cryptoCode: &CryptoValue{ + CryptoType: TypeHash, + Algorithm: "hash", + Crypted: []byte("code"), + }, + verificationCode: "code", + alg: createMockHashAlg(t), + }, + false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := verifyHashedCode(tt.args.cryptoCode, tt.args.verificationCode, tt.args.alg); (err != nil) != tt.wantErr { + t.Errorf("verifyHashedCode() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } } diff --git a/internal/crypto/crypto.go b/internal/crypto/crypto.go index c1b46d69d5..d7f3269321 100644 --- a/internal/crypto/crypto.go +++ b/internal/crypto/crypto.go @@ -99,5 +99,8 @@ func Hash(value []byte, alg HashAlgorithm) (*CryptoValue, error) { } func CompareHash(value *CryptoValue, comparer []byte, alg HashAlgorithm) error { + if value.Algorithm != alg.Algorithm() { + return errors.ThrowInvalidArgument(nil, "CRYPT-HF32f", "value was hash with a different algorithm") + } return alg.CompareHash(value.Crypted, comparer) } diff --git a/internal/crypto/generate.go b/internal/crypto/generate.go index 4c43e7e9b3..fd3de9f759 100644 --- a/internal/crypto/generate.go +++ b/internal/crypto/generate.go @@ -1,3 +1,4 @@ package crypto //go:generate mockgen -source crypto.go -destination ./crypto_mock.go -package crypto +//go:generate mockgen -source code.go -destination ./code_mock.go -package crypto From 78e6d1909834bf748ffd9573eaa26975cbfea1f0 Mon Sep 17 00:00:00 2001 From: Fabiennne Date: Mon, 30 Mar 2020 11:42:22 +0200 Subject: [PATCH 34/39] fix: reformat test --- internal/proto/struct_test.go | 144 ++++++++++++++++++++++++---------- 1 file changed, 103 insertions(+), 41 deletions(-) diff --git a/internal/proto/struct_test.go b/internal/proto/struct_test.go index eeed7c63f3..53e2503f1c 100644 --- a/internal/proto/struct_test.go +++ b/internal/proto/struct_test.go @@ -4,50 +4,112 @@ import ( "testing" pb_struct "github.com/golang/protobuf/ptypes/struct" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) -func TestToPBStruct(t *testing.T) { - obj := struct { - ID string - Name string - Seq uint64 - }{ - ID: "asdf", - Name: "ueli", - Seq: 208582075, +func Test_ToPBStruct(t *testing.T) { + type obj struct { + ID string + Seq uint64 + } + type args struct { + obj obj + } + tests := []struct { + name string + args args + wantErr bool + length int + result obj + }{ + { + name: "to pb stuct", + args: args{ + obj: obj{ID: "ID", Seq: 12345}, + }, + wantErr: false, + length: 2, + result: obj{ID: "ID", Seq: 12345}, + }, + { + name: "empty struct", + args: args{ + obj: obj{}, + }, + wantErr: false, + length: 2, + result: obj{ID: "", Seq: 0}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + fields, err := ToPBStruct(tt.args.obj) + if tt.wantErr && err == nil { + t.Errorf("got wrong result, should get err: actual: %v ", err) + } + if !tt.wantErr && len(fields.Fields) != tt.length { + t.Errorf("got wrong result length, expecting: %v, actual: %v ", tt.length, len(fields.Fields)) + } + if !tt.wantErr && tt.result.ID != fields.Fields["ID"].GetStringValue() { + t.Errorf("got wrong result, ID should be same: expecting: %v, actual: %v ", tt.result.ID, fields.Fields["ID"].GetStringValue()) + } + if !tt.wantErr && int(tt.result.Seq) != int(fields.Fields["Seq"].GetNumberValue()) { + t.Errorf("got wrong result, Seq should be same: expecting: %v, actual: %v ", tt.result.Seq, fields.Fields["Seq"].GetStringValue()) + } + }) } - fields, err := ToPBStruct(&obj) - require.NoError(t, err) - require.Len(t, fields.Fields, 3) - - assert.Equal(t, obj.ID, fields.Fields["ID"].GetStringValue()) - assert.Equal(t, int(obj.Seq), int(fields.Fields["Seq"].GetNumberValue())) - assert.Equal(t, obj.Name, fields.Fields["Name"].GetStringValue()) } -func TestFromPBStruct(t *testing.T) { - name := "ueli" - id := "asdf" - seq := float64(208582075) - s := &pb_struct.Struct{Fields: map[string]*pb_struct.Value{ - "ID": &pb_struct.Value{Kind: &pb_struct.Value_StringValue{StringValue: id}}, - "Name": &pb_struct.Value{Kind: &pb_struct.Value_StringValue{StringValue: name}}, - "Seq": &pb_struct.Value{Kind: &pb_struct.Value_NumberValue{NumberValue: seq}}, - }} - - obj := struct { - ID string - Name string - Seq uint64 - }{} - - err := FromPBStruct(&obj, s) - require.NoError(t, err) - - assert.Equal(t, id, obj.ID) - assert.Equal(t, name, obj.Name) - assert.Equal(t, int(seq), int(obj.Seq)) +func Test_FromPBStruct(t *testing.T) { + type obj struct { + ID string + Seq uint64 + } + type args struct { + obj *obj + fields *pb_struct.Struct + } + tests := []struct { + name string + args args + wantErr bool + result obj + }{ + { + name: "from pb stuct", + args: args{ + obj: &obj{}, + fields: &pb_struct.Struct{Fields: map[string]*pb_struct.Value{ + "ID": &pb_struct.Value{Kind: &pb_struct.Value_StringValue{StringValue: "ID"}}, + "Seq": &pb_struct.Value{Kind: &pb_struct.Value_NumberValue{NumberValue: 12345}}, + }, + }, + }, + wantErr: false, + result: obj{ID: "ID", Seq: 12345}, + }, + { + name: "no fields", + args: args{ + obj: &obj{}, + fields: &pb_struct.Struct{Fields: map[string]*pb_struct.Value{}, + }, + }, + wantErr: false, + result: obj{ID: "", Seq: 0}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := FromPBStruct(tt.args.obj, tt.args.fields) + if tt.wantErr && err == nil { + t.Errorf("got wrong result, should get err: actual: %v ", err) + } + if !tt.wantErr && tt.result.ID != tt.args.obj.ID { + t.Errorf("got wrong result, ID should be same: expecting: %v, actual: %v ", tt.result.ID, tt.args.obj.ID) + } + if !tt.wantErr && int(tt.result.Seq) != int(tt.args.obj.Seq) { + t.Errorf("got wrong result, Seq should be same: expecting: %v, actual: %v ", tt.result.Seq, tt.args.obj.Seq) + } + }) + } } From 96b1817d62a0877061dbc675fe9a2f70dd501d2b Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Mon, 30 Mar 2020 11:44:17 +0200 Subject: [PATCH 35/39] add multi files config test and some more --- internal/config/config_test.go | 37 +++++++++- internal/config/testdata/more_data.yaml | 1 + internal/crypto/aes_test.go | 1 + internal/crypto/code_mock.go | 90 +++++++++++++++++++++++++ 4 files changed, 127 insertions(+), 2 deletions(-) create mode 100644 internal/config/testdata/more_data.yaml create mode 100644 internal/crypto/code_mock.go diff --git a/internal/config/config_test.go b/internal/config/config_test.go index ba517b6061..98221851dc 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -17,6 +17,11 @@ type validatable struct { Test bool } +type multiple struct { + Test bool + MoreData string +} + func (v *validatable) Validate() error { if v.Test { return nil @@ -33,22 +38,25 @@ func TestRead(t *testing.T) { name string args args wantErr bool + want interface{} }{ { "not supoorted config file error", args{ configFiles: []string{"notsupported.unknown"}, - obj: nil, + obj: &test{}, }, true, + &test{}, }, { "non existing config file error", args{ configFiles: []string{"nonexisting.yaml"}, - obj: nil, + obj: &test{}, }, true, + &test{}, }, { "non parsable config file error", @@ -57,6 +65,7 @@ func TestRead(t *testing.T) { obj: &test{}, }, true, + &test{}, }, { "invalid parsable config file error", @@ -65,6 +74,16 @@ func TestRead(t *testing.T) { obj: &validatable{}, }, true, + &validatable{}, + }, + { + "multiple files, one non parsable error ", + args{ + configFiles: []string{"./testdata/non_parsable.json", "./testdata/more_data.yaml"}, + obj: &multiple{}, + }, + true, + &multiple{}, }, { "parsable config file ok", @@ -73,6 +92,16 @@ func TestRead(t *testing.T) { obj: &test{}, }, false, + &test{Test: true}, + }, + { + "multiple parsable config files ok", + args{ + configFiles: []string{"./testdata/valid.json", "./testdata/more_data.yaml"}, + obj: &multiple{}, + }, + false, + &multiple{Test: true, MoreData: "data"}, }, { "valid parsable config file ok", @@ -81,6 +110,7 @@ func TestRead(t *testing.T) { obj: &validatable{}, }, false, + &validatable{Test: true}, }, } for _, tt := range tests { @@ -88,6 +118,9 @@ func TestRead(t *testing.T) { if err := Read(tt.args.obj, tt.args.configFiles...); (err != nil) != tt.wantErr { t.Errorf("Read() error = %v, wantErr %v", err, tt.wantErr) } + if !reflect.DeepEqual(tt.args.obj, tt.want) { + t.Errorf("Read() got = %v, want = %v", tt.args.obj, tt.want) + } }) } } diff --git a/internal/config/testdata/more_data.yaml b/internal/config/testdata/more_data.yaml new file mode 100644 index 0000000000..d8fc5877da --- /dev/null +++ b/internal/config/testdata/more_data.yaml @@ -0,0 +1 @@ +MoreData: data diff --git a/internal/crypto/aes_test.go b/internal/crypto/aes_test.go index c7e31de3d5..87af88d0be 100644 --- a/internal/crypto/aes_test.go +++ b/internal/crypto/aes_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" ) +//TODO: refactor test style func TestDecrypt_OK(t *testing.T) { encryptedpw, err := EncryptAESString("ThisIsMySecretPw", "passphrasewhichneedstobe32bytes!") assert.NoError(t, err) diff --git a/internal/crypto/code_mock.go b/internal/crypto/code_mock.go new file mode 100644 index 0000000000..916a7c225d --- /dev/null +++ b/internal/crypto/code_mock.go @@ -0,0 +1,90 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: code.go + +// Package crypto is a generated GoMock package. +package crypto + +import ( + gomock "github.com/golang/mock/gomock" + reflect "reflect" + time "time" +) + +// MockGenerator is a mock of Generator interface +type MockGenerator struct { + ctrl *gomock.Controller + recorder *MockGeneratorMockRecorder +} + +// MockGeneratorMockRecorder is the mock recorder for MockGenerator +type MockGeneratorMockRecorder struct { + mock *MockGenerator +} + +// NewMockGenerator creates a new mock instance +func NewMockGenerator(ctrl *gomock.Controller) *MockGenerator { + mock := &MockGenerator{ctrl: ctrl} + mock.recorder = &MockGeneratorMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockGenerator) EXPECT() *MockGeneratorMockRecorder { + return m.recorder +} + +// Length mocks base method +func (m *MockGenerator) Length() uint { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Length") + ret0, _ := ret[0].(uint) + return ret0 +} + +// Length indicates an expected call of Length +func (mr *MockGeneratorMockRecorder) Length() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Length", reflect.TypeOf((*MockGenerator)(nil).Length)) +} + +// Expiry mocks base method +func (m *MockGenerator) Expiry() time.Duration { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Expiry") + ret0, _ := ret[0].(time.Duration) + return ret0 +} + +// Expiry indicates an expected call of Expiry +func (mr *MockGeneratorMockRecorder) Expiry() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Expiry", reflect.TypeOf((*MockGenerator)(nil).Expiry)) +} + +// Alg mocks base method +func (m *MockGenerator) Alg() Crypto { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Alg") + ret0, _ := ret[0].(Crypto) + return ret0 +} + +// Alg indicates an expected call of Alg +func (mr *MockGeneratorMockRecorder) Alg() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Alg", reflect.TypeOf((*MockGenerator)(nil).Alg)) +} + +// Runes mocks base method +func (m *MockGenerator) Runes() []rune { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Runes") + ret0, _ := ret[0].([]rune) + return ret0 +} + +// Runes indicates an expected call of Runes +func (mr *MockGeneratorMockRecorder) Runes() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Runes", reflect.TypeOf((*MockGenerator)(nil).Runes)) +} From 40e4f69ca3711d04e406f6af303034d5fc7fb155 Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Mon, 30 Mar 2020 11:52:08 +0200 Subject: [PATCH 36/39] change context keys and fix tests --- internal/api/auth/authorization_test.go | 2 +- internal/api/auth/context.go | 14 +++++++++----- internal/api/auth/permissions.go | 2 +- internal/api/auth/permissions_test.go | 2 +- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/internal/api/auth/authorization_test.go b/internal/api/auth/authorization_test.go index ac1193385e..d140758321 100644 --- a/internal/api/auth/authorization_test.go +++ b/internal/api/auth/authorization_test.go @@ -270,7 +270,7 @@ func Test_GetPermissionCtxIDs(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := GetPermissionCtxIDs(tt.args.perms) - if !EqualStringArray(result, tt.result) { + if !equalStringArray(result, tt.result) { t.Errorf("got wrong result, expecting: %v, actual: %v ", tt.result, result) } }) diff --git a/internal/api/auth/context.go b/internal/api/auth/context.go index 78ef0bc252..e0c87929e5 100644 --- a/internal/api/auth/context.go +++ b/internal/api/auth/context.go @@ -6,8 +6,12 @@ import ( "github.com/caos/logging" ) -type CtxKeyPermissions struct{} -type CtxKeyData struct{} +type key int + +var ( + permissionsKey key + dataKey key +) type CtxData struct { UserID string @@ -42,15 +46,15 @@ func VerifyTokenAndWriteCtxData(ctx context.Context, token, orgID string, t Toke projectID, err := t.GetProjectIDByClientID(ctx, clientID) logging.LogWithFields("AUTH-GfAoV", "clientID", clientID).OnError(err).Warn("could not read projectid by clientid") - return context.WithValue(ctx, CtxKeyData{}, CtxData{UserID: userID, OrgID: orgID, ProjectID: projectID, AgentID: agentID}), nil + return context.WithValue(ctx, dataKey, CtxData{UserID: userID, OrgID: orgID, ProjectID: projectID, AgentID: agentID}), nil } func GetCtxData(ctx context.Context) CtxData { - ctxData, _ := ctx.Value(CtxKeyData{}).(CtxData) + ctxData, _ := ctx.Value(dataKey).(CtxData) return ctxData } func GetPermissionsFromCtx(ctx context.Context) []string { - ctxPermission, _ := ctx.Value(CtxKeyPermissions{}).([]string) + ctxPermission, _ := ctx.Value(permissionsKey).([]string) return ctxPermission } diff --git a/internal/api/auth/permissions.go b/internal/api/auth/permissions.go index d7ca516a9d..04c6713915 100644 --- a/internal/api/auth/permissions.go +++ b/internal/api/auth/permissions.go @@ -16,7 +16,7 @@ func getUserMethodPermissions(ctx context.Context, t TokenVerifier, requiredPerm return nil, nil, err } permissions := mapGrantsToPermissions(requiredPerm, grants, authConfig) - return context.WithValue(ctx, CtxKeyPermissions{}, permissions), permissions, nil + return context.WithValue(ctx, permissionsKey, permissions), permissions, nil } func mapGrantsToPermissions(requiredPerm string, grants []*Grant, authConfig *Config) []string { diff --git a/internal/api/auth/permissions_test.go b/internal/api/auth/permissions_test.go index d2afc36dfc..ba67f0d25f 100644 --- a/internal/api/auth/permissions_test.go +++ b/internal/api/auth/permissions_test.go @@ -8,7 +8,7 @@ import ( ) func getTestCtx(userID, orgID string) context.Context { - return context.WithValue(context.Background(), CtxKeyData{}, CtxData{UserID: userID, OrgID: orgID}) + return context.WithValue(context.Background(), dataKey, CtxData{UserID: userID, OrgID: orgID}) } type testVerifier struct { From affd2da40a47d01e483a8f12f852db51a8ae0b2c Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Mon, 30 Mar 2020 11:57:56 +0200 Subject: [PATCH 37/39] update logging version --- cmd/zitadel/main.go | 7 ++++--- cmd/zitadel/startup.yaml | 3 ++- go.mod | 5 +++-- go.sum | 10 ++++++---- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/cmd/zitadel/main.go b/cmd/zitadel/main.go index 5d0b1e6a9c..fc5f748139 100644 --- a/cmd/zitadel/main.go +++ b/cmd/zitadel/main.go @@ -8,6 +8,7 @@ import ( authz "github.com/caos/zitadel/internal/api/auth" "github.com/caos/zitadel/internal/config" + tracing "github.com/caos/zitadel/internal/tracing/config" "github.com/caos/zitadel/pkg/admin" "github.com/caos/zitadel/pkg/auth" "github.com/caos/zitadel/pkg/console" @@ -22,9 +23,9 @@ type Config struct { Admin admin.Config Console console.Config - //Log //TODO: add - //Tracing tracing.TracingConfig //TODO: add - AuthZ authz.Config + Log logging.Config + Tracing tracing.TracingConfig + AuthZ authz.Config } func main() { diff --git a/cmd/zitadel/startup.yaml b/cmd/zitadel/startup.yaml index c84f9015a1..abf809b34b 100644 --- a/cmd/zitadel/startup.yaml +++ b/cmd/zitadel/startup.yaml @@ -7,7 +7,8 @@ Tracing: Log: Level: debug - Formatter: text + Formatter: + Format: text Mgmt: API: diff --git a/go.mod b/go.mod index 731d99ee77..4f7af60649 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/Masterminds/semver v1.5.0 // indirect github.com/Masterminds/sprig v2.22.0+incompatible github.com/aws/aws-sdk-go v1.29.16 // indirect - github.com/caos/logging v0.0.0-20191210002624-b3260f690a6a + github.com/caos/logging v0.0.1 github.com/ghodss/yaml v1.0.0 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b github.com/golang/mock v1.4.3 @@ -25,11 +25,12 @@ require ( github.com/mitchellh/copystructure v1.0.0 // indirect github.com/nicksnyder/go-i18n/v2 v2.0.3 github.com/rs/cors v1.7.0 + github.com/sirupsen/logrus v1.5.0 // indirect github.com/stretchr/testify v1.5.1 go.opencensus.io v0.22.3 golang.org/x/crypto v0.0.0-20200320181102-891825fb96df golang.org/x/net v0.0.0-20200320220750-118fecf932d8 // indirect - golang.org/x/sys v0.0.0-20200321134203-328b4cd54aae // indirect + golang.org/x/sys v0.0.0-20200327173247-9dae0f8f5775 // indirect golang.org/x/text v0.3.2 golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56 google.golang.org/api v0.20.0 // indirect diff --git a/go.sum b/go.sum index c277b44880..f253cef29c 100644 --- a/go.sum +++ b/go.sum @@ -32,8 +32,8 @@ github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQY github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.29.16 h1:Gbtod7Y4W/Ai7wPtesdvgGVTkFN8JxAaGouRLlcQfQs= github.com/aws/aws-sdk-go v1.29.16/go.mod h1:1KvfttTE3SPKMpo8g2c6jL3ZKfXtFvKscTgahTma5Xg= -github.com/caos/logging v0.0.0-20191210002624-b3260f690a6a h1:HOU/3xL/afsZ+2aCstfJlrzRkwYMTFR1TIEgps5ny8s= -github.com/caos/logging v0.0.0-20191210002624-b3260f690a6a/go.mod h1:9LKiDE2ChuGv6CHYif/kiugrfEXu9AwDiFWSreX7Wp0= +github.com/caos/logging v0.0.1 h1:YSGtO2/+5OWdwilBCou50akoDHAT/OhkbrolkVlR6U0= +github.com/caos/logging v0.0.1/go.mod h1:9LKiDE2ChuGv6CHYif/kiugrfEXu9AwDiFWSreX7Wp0= github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= @@ -140,6 +140,8 @@ github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.5.0 h1:1N5EYkVAPEywqZRJd7cwnRtCb6xJx7NH3T3WUTF980Q= +github.com/sirupsen/logrus v1.5.0/go.mod h1:+F7Ogzej0PZc/94MaYx/nvG9jOFMD2osvC3s+Squfpo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= @@ -234,8 +236,8 @@ golang.org/x/sys v0.0.0-20191206220618-eeba5f6aabab h1:FvshnhkKW+LO3HWHodML8kuVX golang.org/x/sys v0.0.0-20191206220618-eeba5f6aabab/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200321134203-328b4cd54aae h1:3tcmuaB7wwSZtelmiv479UjUB+vviwABz7a133ZwOKQ= -golang.org/x/sys v0.0.0-20200321134203-328b4cd54aae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200327173247-9dae0f8f5775 h1:TC0v2RSO1u2kn1ZugjrFXkRZAEaqMN/RW+OTZkBzmLE= +golang.org/x/sys v0.0.0-20200327173247-9dae0f8f5775/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From 39039dde626a975fff5a0f77cfb69fc99b8d17a6 Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Mon, 30 Mar 2020 13:17:49 +0200 Subject: [PATCH 38/39] fix tracing/statusFromError --- internal/api/grpc/caos_errors.go | 4 ++-- internal/tracing/span.go | 9 +++------ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/internal/api/grpc/caos_errors.go b/internal/api/grpc/caos_errors.go index 5ed7fa95da..413a2fd128 100644 --- a/internal/api/grpc/caos_errors.go +++ b/internal/api/grpc/caos_errors.go @@ -11,14 +11,14 @@ func CaosToGRPCError(err error) error { if err == nil { return nil } - code, msg, ok := extract(err) + code, msg, ok := Extract(err) if !ok { return status.Convert(err).Err() } return status.Error(code, msg) } -func extract(err error) (c codes.Code, msg string, ok bool) { +func Extract(err error) (c codes.Code, msg string, ok bool) { switch caosErr := err.(type) { case *caos_errs.AlreadyExistsError: return codes.AlreadyExists, caosErr.GetMessage(), true diff --git a/internal/tracing/span.go b/internal/tracing/span.go index 1ad46ca0b1..aff92822c2 100644 --- a/internal/tracing/span.go +++ b/internal/tracing/span.go @@ -5,9 +5,8 @@ import ( "strconv" "go.opencensus.io/trace" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" + "github.com/caos/zitadel/internal/api/grpc" "github.com/caos/zitadel/internal/errors" ) @@ -41,10 +40,8 @@ func (s *Span) SetStatusByError(err error) { } func statusFromError(err error) trace.Status { - if statusErr, ok := status.FromError(err); ok { - return trace.Status{Code: int32(statusErr.Code()), Message: statusErr.Message()} - } - return trace.Status{Code: int32(codes.Unknown), Message: "Unknown"} + code, msg, _ := grpc.Extract(err) + return trace.Status{Code: int32(code), Message: msg} } // AddAnnotation creates an annotation. The annotation will not be added to the tracing use Annotate(msg) afterwards From c564f47b92b7000afcd9b0ee668a2b6f2a6e4376 Mon Sep 17 00:00:00 2001 From: livio-a Date: Mon, 30 Mar 2020 16:53:29 +0200 Subject: [PATCH 39/39] single marshaller --- internal/proto/struct.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/internal/proto/struct.go b/internal/proto/struct.go index f1b5eb29f9..5c7b93b430 100644 --- a/internal/proto/struct.go +++ b/internal/proto/struct.go @@ -10,6 +10,10 @@ import ( "github.com/caos/logging" ) +var ( + marshaller = new(jsonpb.Marshaler) +) + func MustToPBStruct(object interface{}) *pb_struct.Struct { s, err := ToPBStruct(object) logging.Log("PROTO-7Aa3t").OnError(err).Panic("unable to map object to pb-struct") @@ -38,7 +42,6 @@ func MustFromPBStruct(object interface{}, s *pb_struct.Struct) { } func FromPBStruct(object interface{}, s *pb_struct.Struct) error { - marshaller := new(jsonpb.Marshaler) jsonString, err := marshaller.MarshalToString(s) if err != nil { return err