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