Authenticate Handler API and SDK, and much more (#183)

This commit is contained in:
Todd Knight authored and GitHub committed 2020-07-14 17:32:47 -04:00
1 parent acce195dcb
commit 28dbcd84bd
89 files changed
+5296 -1943

No files matched your search

+78
View File
@@ -0,0 +1,78 @@
// Code generated by "make api"; DO NOT EDIT.
package authtokens
import (
"encoding/json"
"strings"
"time"
"github.com/fatih/structs"
"github.com/hashicorp/watchtower/api"
"github.com/hashicorp/watchtower/api/internal/strutil"
)
type AuthToken struct {
Client *api.Client `json:"-"`
defaultFields []string
// The ID of the AuthToken
// Output only.
Id string `json:"id,omitempty"`
// The token. This will only be populated after login and is only ever visible to the end user whose login
// request resulted in this auth token being created.
// Output only.
Token string `json:"token,omitempty"`
// The id of the user of this AuthToken.
// Output only.
UserId string `json:"user_id,omitempty"`
// The id of the user of this AuthToken.
// Output only.
AuthMethodId string `json:"auth_method_id,omitempty"`
// The time this resource was created
// Output only.
CreatedTime time.Time `json:"created_time,omitempty"`
// The time this resource was last updated.
// Output only.
UpdatedTime time.Time `json:"updated_time,omitempty"`
// The approximate time this AuthToken was last used.
// Output only.
ApproximateLastUsedTime time.Time `json:"approximate_last_used_time,omitempty"`
// The time this AuthToken expires.
// Output only.
ExpirationTime time.Time `json:"expiration_time,omitempty"`
}
func (s *AuthToken) SetDefault(key string) {
lowerKey := strings.ToLower(key)
validMap := map[string]string{"approximatelastusedtime": "approximate_last_used_time", "authmethodid": "auth_method_id", "createdtime": "created_time", "expirationtime": "expiration_time", "id": "id", "token": "token", "updatedtime": "updated_time", "userid": "user_id"}
for k, v := range validMap {
if k == lowerKey || v == lowerKey {
s.defaultFields = strutil.AppendIfMissing(s.defaultFields, v)
return
}
}
}
func (s *AuthToken) UnsetDefault(key string) {
lowerKey := strings.ToLower(key)
validMap := map[string]string{"approximatelastusedtime": "approximate_last_used_time", "authmethodid": "auth_method_id", "createdtime": "created_time", "expirationtime": "expiration_time", "id": "id", "token": "token", "updatedtime": "updated_time", "userid": "user_id"}
for k, v := range validMap {
if k == lowerKey || v == lowerKey {
s.defaultFields = strutil.StrListDelete(s.defaultFields, v)
return
}
}
}
func (s AuthToken) MarshalJSON() ([]byte, error) {
m := structs.Map(s)
if m == nil {
m = make(map[string]interface{})
}
for _, k := range s.defaultFields {
m[k] = nil
}
return json.Marshal(m)
}
+39 -7
View File
@@ -143,6 +143,7 @@ func DefaultConfig() (*Config, error) {
Addr: "https://127.0.0.1:9200",
HttpClient: cleanhttp.DefaultPooledClient(),
Timeout: time.Second * 60,
TLSConfig: &TLSConfig{},
}
// We read the environment now; after DefaultClient returns we can override
@@ -217,10 +218,10 @@ func (c *Config) ConfigureTLS() error {
return nil
}
// setAddress parses a given string and looks for org and project info, setting
// the actual address to the base. Note that if a very malformed URL is passed
// in, this may not return what one expects. For now this is on purpose to
// avoid requiring error handling.
// setAddr parses a given string and looks for org and project info, setting the
// actual address to the base. Note that if a very malformed URL is passed in,
// this may not return what one expects. For now this is on purpose to avoid
// requiring error handling.
//
// This also removes any trailing "/v1"; we'll use that in our commands so we
// don't require it from users.
@@ -449,6 +450,14 @@ func (c *Client) SetAddr(addr string) error {
return c.config.setAddr(addr)
}
// Org fetches the org the client will use by default
func (c *Client) Org() string {
c.modifyLock.Lock()
defer c.modifyLock.Unlock()
return c.config.Org
}
// SetOrg sets the org the client will use by default
func (c *Client) SetOrg(org string) {
c.modifyLock.Lock()
@@ -457,6 +466,14 @@ func (c *Client) SetOrg(org string) {
c.config.Org = org
}
// Project fetches the project the client will use by default
func (c *Client) Project() string {
c.modifyLock.Lock()
defer c.modifyLock.Unlock()
return c.config.Project
}
// SetProject sets the project the client will use by default
func (c *Client) SetProject(project string) {
c.modifyLock.Lock()
@@ -519,6 +536,14 @@ func (c *Client) SetOutputCurlString(curl bool) {
c.config.OutputCurlString = curl
}
// Token gets the configured token.
func (c *Client) Token() string {
c.modifyLock.Lock()
defer c.modifyLock.Unlock()
return c.config.Token
}
// SetToken sets the token directly. This won't perform any auth
// verification, it simply sets the token properly for future requests.
func (c *Client) SetToken(token string) {
@@ -700,18 +725,25 @@ func (c *Client) NewRequest(ctx context.Context, method, requestPath string, bod
orgProjPath = path.Join(orgProjPath, "projects", project)
}
p := path.Join(u.Path, "/v1", orgProjPath)
if strings.HasPrefix(requestPath, ":") {
p = p + requestPath
} else {
p = path.Join(p, requestPath)
}
req := &http.Request{
Method: method,
URL: &url.URL{
User: u.User,
Scheme: u.Scheme,
Host: host,
Path: path.Join(u.Path, "/v1", orgProjPath, requestPath),
Path: p,
},
Host: u.Host,
}
req.Header = headers
req.Header.Add("authorization", "bearer: "+token)
req.Header.Add("authorization", "Bearer "+token)
req.Header.Set("content-type", "application/json")
if ctx != nil {
req = req.WithContext(ctx)
@@ -786,7 +818,7 @@ func (c *Client) Do(r *retryablehttp.Request) (*Response, error) {
}
result, err := client.Do(r)
if result != nil && err == nil && result.StatusCode == 307 {
if result != nil && err == nil && result.StatusCode == http.StatusTemporaryRedirect {
loc, err := result.Location()
if err != nil {
return nil, fmt.Errorf("error getting new location during redirect: %w", err)
+20 -5
View File
@@ -3,6 +3,7 @@ package api
import (
"encoding/json"
"strings"
"github.com/fatih/structs"
@@ -13,22 +14,36 @@ type Error struct {
defaultFields []string
// The HTTP Status code applicable to this error
Status *int32 `json:"status,omitempty"`
Status int32 `json:"status,omitempty"`
// An application-specific error string
Code *string `json:"code,omitempty"`
Code string `json:"code,omitempty"`
// A human readable explanation specific to this occurrence of the error
Message *string `json:"message,omitempty"`
Message string `json:"message,omitempty"`
// Additional metadata regarding the error. Depending on the error
// different fields will be populated.
Details *ErrorDetails `json:"details,omitempty"`
}
func (s *Error) SetDefault(key string) {
s.defaultFields = strutil.AppendIfMissing(s.defaultFields, key)
lowerKey := strings.ToLower(key)
validMap := map[string]string{"code": "code", "details": "details", "message": "message", "status": "status"}
for k, v := range validMap {
if k == lowerKey || v == lowerKey {
s.defaultFields = strutil.AppendIfMissing(s.defaultFields, v)
return
}
}
}
func (s *Error) UnsetDefault(key string) {
s.defaultFields = strutil.StrListDelete(s.defaultFields, key)
lowerKey := strings.ToLower(key)
validMap := map[string]string{"code": "code", "details": "details", "message": "message", "status": "status"}
for k, v := range validMap {
if k == lowerKey || v == lowerKey {
s.defaultFields = strutil.StrListDelete(s.defaultFields, v)
return
}
}
}
func (s Error) MarshalJSON() ([]byte, error) {
+19 -4
View File
@@ -3,6 +3,7 @@ package api
import (
"encoding/json"
"strings"
"github.com/fatih/structs"
@@ -12,17 +13,31 @@ import (
type ErrorDetails struct {
defaultFields []string
TraceId *string `json:"TraceId,omitempty"`
RequestId *string `json:"request_id,omitempty"`
TraceId string `json:"TraceId,omitempty"`
RequestId string `json:"request_id,omitempty"`
RequestFields []*FieldError `json:"request_fields,omitempty"`
}
func (s *ErrorDetails) SetDefault(key string) {
s.defaultFields = strutil.AppendIfMissing(s.defaultFields, key)
lowerKey := strings.ToLower(key)
validMap := map[string]string{"requestfields": "request_fields", "requestid": "request_id", "traceid": "TraceId"}
for k, v := range validMap {
if k == lowerKey || v == lowerKey {
s.defaultFields = strutil.AppendIfMissing(s.defaultFields, v)
return
}
}
}
func (s *ErrorDetails) UnsetDefault(key string) {
s.defaultFields = strutil.StrListDelete(s.defaultFields, key)
lowerKey := strings.ToLower(key)
validMap := map[string]string{"requestfields": "request_fields", "requestid": "request_id", "traceid": "TraceId"}
for k, v := range validMap {
if k == lowerKey || v == lowerKey {
s.defaultFields = strutil.StrListDelete(s.defaultFields, v)
return
}
}
}
func (s ErrorDetails) MarshalJSON() ([]byte, error) {
+19 -4
View File
@@ -3,6 +3,7 @@ package api
import (
"encoding/json"
"strings"
"github.com/fatih/structs"
@@ -12,16 +13,30 @@ import (
type FieldError struct {
defaultFields []string
Name *string `json:"name,omitempty"`
Description *string `json:"description,omitempty"`
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
}
func (s *FieldError) SetDefault(key string) {
s.defaultFields = strutil.AppendIfMissing(s.defaultFields, key)
lowerKey := strings.ToLower(key)
validMap := map[string]string{"description": "description", "name": "name"}
for k, v := range validMap {
if k == lowerKey || v == lowerKey {
s.defaultFields = strutil.AppendIfMissing(s.defaultFields, v)
return
}
}
}
func (s *FieldError) UnsetDefault(key string) {
s.defaultFields = strutil.StrListDelete(s.defaultFields, key)
lowerKey := strings.ToLower(key)
validMap := map[string]string{"description": "description", "name": "name"}
for k, v := range validMap {
if k == lowerKey || v == lowerKey {
s.defaultFields = strutil.StrListDelete(s.defaultFields, v)
return
}
}
}
func (s FieldError) MarshalJSON() ([]byte, error) {
+17 -2
View File
@@ -3,6 +3,7 @@ package groups
import (
"encoding/json"
"strings"
"time"
"github.com/fatih/structs"
@@ -34,11 +35,25 @@ type Group struct {
}
func (s *Group) SetDefault(key string) {
s.defaultFields = strutil.AppendIfMissing(s.defaultFields, key)
lowerKey := strings.ToLower(key)
validMap := map[string]string{"createdtime": "created_time", "description": "description", "disabled": "disabled", "id": "id", "name": "name", "updatedtime": "updated_time"}
for k, v := range validMap {
if k == lowerKey || v == lowerKey {
s.defaultFields = strutil.AppendIfMissing(s.defaultFields, v)
return
}
}
}
func (s *Group) UnsetDefault(key string) {
s.defaultFields = strutil.StrListDelete(s.defaultFields, key)
lowerKey := strings.ToLower(key)
validMap := map[string]string{"createdtime": "created_time", "description": "description", "disabled": "disabled", "id": "id", "name": "name", "updatedtime": "updated_time"}
for k, v := range validMap {
if k == lowerKey || v == lowerKey {
s.defaultFields = strutil.StrListDelete(s.defaultFields, v)
return
}
}
}
func (s Group) MarshalJSON() ([]byte, error) {
+5 -5
View File
@@ -116,8 +116,8 @@ func TestGroup_Crud(t *testing.T) {
checkGroup := func(step string, g *groups.Group, apiErr *api.Error, err error, wantedName string) {
assert := assert.New(t)
assert.NoError(err, step)
if !assert.Nil(apiErr, step) && apiErr.Message != nil {
t.Errorf("ApiError message: %q", *apiErr.Message)
if !assert.Nil(apiErr, step) && apiErr.Message != "" {
t.Errorf("ApiError message: %q", apiErr.Message)
}
assert.NotNil(g, "returned no resource", step)
gotName := ""
@@ -216,17 +216,17 @@ func TestGroup_Errors(t *testing.T) {
_, apiErr, err = tt.scope.ReadGroup(ctx, &groups.Group{Id: iam.GroupPrefix + "_doesntexis"})
assert.NoError(err)
assert.NotNil(apiErr)
assert.EqualValues(*apiErr.Status, http.StatusNotFound)
assert.EqualValues(apiErr.Status, http.StatusNotFound)
_, apiErr, err = tt.scope.ReadGroup(ctx, &groups.Group{Id: "invalid id"})
assert.NoError(err)
assert.NotNil(apiErr)
assert.EqualValues(*apiErr.Status, http.StatusBadRequest)
assert.EqualValues(apiErr.Status, http.StatusBadRequest)
_, apiErr, err = tt.scope.UpdateGroup(ctx, &groups.Group{Id: u.Id})
assert.NoError(err)
assert.NotNil(apiErr)
assert.EqualValues(*apiErr.Status, http.StatusBadRequest)
assert.EqualValues(apiErr.Status, http.StatusBadRequest)
})
}
}
+17 -2
View File
@@ -3,6 +3,7 @@ package hosts
import (
"encoding/json"
"strings"
"time"
"github.com/fatih/structs"
@@ -38,11 +39,25 @@ type Host struct {
}
func (s *Host) SetDefault(key string) {
s.defaultFields = strutil.AppendIfMissing(s.defaultFields, key)
lowerKey := strings.ToLower(key)
validMap := map[string]string{"address": "address", "createdtime": "created_time", "description": "description", "disabled": "disabled", "id": "id", "name": "name", "type": "type", "updatedtime": "updated_time"}
for k, v := range validMap {
if k == lowerKey || v == lowerKey {
s.defaultFields = strutil.AppendIfMissing(s.defaultFields, v)
return
}
}
}
func (s *Host) UnsetDefault(key string) {
s.defaultFields = strutil.StrListDelete(s.defaultFields, key)
lowerKey := strings.ToLower(key)
validMap := map[string]string{"address": "address", "createdtime": "created_time", "description": "description", "disabled": "disabled", "id": "id", "name": "name", "type": "type", "updatedtime": "updated_time"}
for k, v := range validMap {
if k == lowerKey || v == lowerKey {
s.defaultFields = strutil.StrListDelete(s.defaultFields, v)
return
}
}
}
func (s Host) MarshalJSON() ([]byte, error) {
+17 -2
View File
@@ -3,6 +3,7 @@ package hosts
import (
"encoding/json"
"strings"
"time"
"github.com/fatih/structs"
@@ -39,11 +40,25 @@ type HostCatalog struct {
}
func (s *HostCatalog) SetDefault(key string) {
s.defaultFields = strutil.AppendIfMissing(s.defaultFields, key)
lowerKey := strings.ToLower(key)
validMap := map[string]string{"attributes": "attributes", "createdtime": "created_time", "description": "description", "disabled": "disabled", "id": "id", "name": "name", "type": "type", "updatedtime": "updated_time"}
for k, v := range validMap {
if k == lowerKey || v == lowerKey {
s.defaultFields = strutil.AppendIfMissing(s.defaultFields, v)
return
}
}
}
func (s *HostCatalog) UnsetDefault(key string) {
s.defaultFields = strutil.StrListDelete(s.defaultFields, key)
lowerKey := strings.ToLower(key)
validMap := map[string]string{"attributes": "attributes", "createdtime": "created_time", "description": "description", "disabled": "disabled", "id": "id", "name": "name", "type": "type", "updatedtime": "updated_time"}
for k, v := range validMap {
if k == lowerKey || v == lowerKey {
s.defaultFields = strutil.StrListDelete(s.defaultFields, v)
return
}
}
}
func (s HostCatalog) MarshalJSON() ([]byte, error) {
+5 -5
View File
@@ -29,8 +29,8 @@ func TestCatalogs_Crud(t *testing.T) {
checkCatalog := func(step string, hc *hosts.HostCatalog, apiErr *api.Error, err error, wantedName string) {
assert := assert.New(t)
assert.NoError(err, step)
if !assert.Nil(apiErr, step) && apiErr.Message != nil {
t.Errorf("ApiError message: %q", *apiErr.Message)
if !assert.Nil(apiErr, step) && apiErr.Message != "" {
t.Errorf("ApiError message: %q", apiErr.Message)
}
assert.NotNil(hc, "returned no resource", step)
gotName := ""
@@ -94,15 +94,15 @@ func TestCatalogs_Errors(t *testing.T) {
assert.NoError(err)
// TODO: Should this be nil instead of just a catalog that has no values set
assert.NotNil(apiErr)
assert.EqualValues(*apiErr.Status, http.StatusNotFound)
assert.EqualValues(apiErr.Status, http.StatusNotFound)
_, apiErr, err = p.ReadHostCatalog(ctx, &hosts.HostCatalog{Id: "invalid id"})
assert.NoError(err)
assert.NotNil(apiErr)
assert.EqualValues(*apiErr.Status, http.StatusBadRequest)
assert.EqualValues(apiErr.Status, http.StatusBadRequest)
_, apiErr, err = p.UpdateHostCatalog(ctx, &hosts.HostCatalog{Id: hc.Id, Type: api.String("Cant Update")})
assert.NoError(err)
assert.NotNil(apiErr)
assert.EqualValues(*apiErr.Status, http.StatusBadRequest)
assert.EqualValues(apiErr.Status, http.StatusBadRequest)
}
+17 -2
View File
@@ -3,6 +3,7 @@ package hosts
import (
"encoding/json"
"strings"
"time"
"github.com/fatih/structs"
@@ -44,11 +45,25 @@ type HostSet struct {
}
func (s *HostSet) SetDefault(key string) {
s.defaultFields = strutil.AppendIfMissing(s.defaultFields, key)
lowerKey := strings.ToLower(key)
validMap := map[string]string{"createdtime": "created_time", "description": "description", "disabled": "disabled", "hosts": "hosts", "id": "id", "name": "name", "size": "size", "type": "type", "updatedtime": "updated_time"}
for k, v := range validMap {
if k == lowerKey || v == lowerKey {
s.defaultFields = strutil.AppendIfMissing(s.defaultFields, v)
return
}
}
}
func (s *HostSet) UnsetDefault(key string) {
s.defaultFields = strutil.StrListDelete(s.defaultFields, key)
lowerKey := strings.ToLower(key)
validMap := map[string]string{"createdtime": "created_time", "description": "description", "disabled": "disabled", "hosts": "hosts", "id": "id", "name": "name", "size": "size", "type": "type", "updatedtime": "updated_time"}
for k, v := range validMap {
if k == lowerKey || v == lowerKey {
s.defaultFields = strutil.StrListDelete(s.defaultFields, v)
return
}
}
}
func (s HostSet) MarshalJSON() ([]byte, error) {
+86 -117
View File
@@ -12,150 +12,119 @@ type structInfo struct {
parentName string
detailName string
templateType templateType
nameJsonMap map[string]string
}
var inputStructs = []*structInfo{
{
os.Getenv("GEN_BASEPATH") + "/internal/gen/controller/api/error.pb.go",
"Error",
os.Getenv("GEN_BASEPATH") + "/api/error.gen.go",
"Error",
"api",
"",
"",
"",
templateTypeResource,
inFile: os.Getenv("GEN_BASEPATH") + "/internal/gen/controller/api/error.pb.go",
inName: "Error",
outFile: os.Getenv("GEN_BASEPATH") + "/api/error.gen.go",
outName: "Error",
outPkg: "api",
},
{
os.Getenv("GEN_BASEPATH") + "/internal/gen/controller/api/error.pb.go",
"ErrorDetails",
os.Getenv("GEN_BASEPATH") + "/api/error_details.gen.go",
"ErrorDetails",
"api",
"",
"",
"",
templateTypeResource,
inFile: os.Getenv("GEN_BASEPATH") + "/internal/gen/controller/api/error.pb.go",
inName: "ErrorDetails",
outFile: os.Getenv("GEN_BASEPATH") + "/api/error_details.gen.go",
outName: "ErrorDetails",
outPkg: "api",
},
{
os.Getenv("GEN_BASEPATH") + "/internal/gen/controller/api/error.pb.go",
"FieldError",
os.Getenv("GEN_BASEPATH") + "/api/field_error.gen.go",
"FieldError",
"api",
"",
"",
"",
templateTypeResource,
inFile: os.Getenv("GEN_BASEPATH") + "/internal/gen/controller/api/error.pb.go",
inName: "FieldError",
outFile: os.Getenv("GEN_BASEPATH") + "/api/field_error.gen.go",
outName: "FieldError",
outPkg: "api",
},
{
os.Getenv("GEN_BASEPATH") + "/internal/gen/controller/api/resources/hosts/host.pb.go",
"Host",
os.Getenv("GEN_BASEPATH") + "/api/hosts/host.gen.go",
"Host",
"hosts",
"",
"",
"",
templateTypeResource,
inFile: os.Getenv("GEN_BASEPATH") + "/internal/gen/controller/api/resources/hosts/host.pb.go",
inName: "Host",
outFile: os.Getenv("GEN_BASEPATH") + "/api/hosts/host.gen.go",
outName: "Host",
outPkg: "hosts",
},
{
os.Getenv("GEN_BASEPATH") + "/internal/gen/controller/api/resources/hosts/host_set.pb.go",
"HostSet",
os.Getenv("GEN_BASEPATH") + "/api/hosts/host_set.gen.go",
"HostSet",
"hosts",
"",
"",
"",
templateTypeResource,
inFile: os.Getenv("GEN_BASEPATH") + "/internal/gen/controller/api/resources/hosts/host_set.pb.go",
inName: "HostSet",
outFile: os.Getenv("GEN_BASEPATH") + "/api/hosts/host_set.gen.go",
outName: "HostSet",
outPkg: "hosts",
},
{
os.Getenv("GEN_BASEPATH") + "/internal/gen/controller/api/resources/hosts/host_catalog.pb.go",
"HostCatalog",
os.Getenv("GEN_BASEPATH") + "/api/hosts/host_catalog.gen.go",
"HostCatalog",
"hosts",
"",
"",
"",
templateTypeResource,
inFile: os.Getenv("GEN_BASEPATH") + "/internal/gen/controller/api/resources/hosts/host_catalog.pb.go",
inName: "HostCatalog",
outFile: os.Getenv("GEN_BASEPATH") + "/api/hosts/host_catalog.gen.go",
outName: "HostCatalog",
outPkg: "hosts",
},
{
os.Getenv("GEN_BASEPATH") + "/internal/gen/controller/api/resources/scopes/org.pb.go",
"Org",
os.Getenv("GEN_BASEPATH") + "/api/scopes/org.gen.go",
"Org",
"scopes",
"",
"",
"",
templateTypeResource,
inFile: os.Getenv("GEN_BASEPATH") + "/internal/gen/controller/api/resources/scopes/org.pb.go",
inName: "Org",
outFile: os.Getenv("GEN_BASEPATH") + "/api/scopes/org.gen.go",
outName: "Org",
outPkg: "scopes",
},
{
os.Getenv("GEN_BASEPATH") + "/internal/gen/controller/api/resources/scopes/project.pb.go",
"Project",
os.Getenv("GEN_BASEPATH") + "/api/scopes/project.gen.go",
"Project",
"scopes",
"",
"",
"",
templateTypeResource,
inFile: os.Getenv("GEN_BASEPATH") + "/internal/gen/controller/api/resources/authtokens/authtoken.pb.go",
inName: "AuthToken",
outFile: os.Getenv("GEN_BASEPATH") + "/api/authtokens/authtoken.gen.go",
outName: "AuthToken",
outPkg: "authtokens",
},
{
os.Getenv("GEN_BASEPATH") + "/internal/gen/controller/api/resources/users/user.pb.go",
"User",
os.Getenv("GEN_BASEPATH") + "/api/users/user.gen.go",
"User",
"users",
"",
"",
"",
templateTypeResource,
inFile: os.Getenv("GEN_BASEPATH") + "/internal/gen/controller/api/resources/scopes/project.pb.go",
inName: "Project",
outFile: os.Getenv("GEN_BASEPATH") + "/api/scopes/project.gen.go",
outName: "Project",
outPkg: "scopes",
},
{
os.Getenv("GEN_BASEPATH") + "/internal/gen/controller/api/resources/groups/group.pb.go",
"Group",
os.Getenv("GEN_BASEPATH") + "/api/groups/group.gen.go",
"Group",
"groups",
"",
"",
"",
templateTypeResource,
inFile: os.Getenv("GEN_BASEPATH") + "/internal/gen/controller/api/resources/users/user.pb.go",
inName: "User",
outFile: os.Getenv("GEN_BASEPATH") + "/api/users/user.gen.go",
outName: "User",
outPkg: "users",
},
{
os.Getenv("GEN_BASEPATH") + "/internal/gen/controller/api/resources/roles/role.pb.go",
"Role",
os.Getenv("GEN_BASEPATH") + "/api/roles/role.gen.go",
"Role",
"roles",
"",
"",
"",
templateTypeResource,
inFile: os.Getenv("GEN_BASEPATH") + "/internal/gen/controller/api/resources/groups/group.pb.go",
inName: "Group",
outFile: os.Getenv("GEN_BASEPATH") + "/api/groups/group.gen.go",
outName: "Group",
outPkg: "groups",
},
{
os.Getenv("GEN_BASEPATH") + "/internal/gen/controller/api/resources/hosts/host_catalog.pb.go",
"StaticHostCatalogDetails",
os.Getenv("GEN_BASEPATH") + "/api/hosts/static_host_catalog.gen.go",
"StaticHostCatalogDetails",
"hosts",
"",
"HostCatalog",
"StaticHostCatalog",
templateTypeDetail,
inFile: os.Getenv("GEN_BASEPATH") + "/internal/gen/controller/api/resources/roles/role.pb.go",
inName: "Role",
outFile: os.Getenv("GEN_BASEPATH") + "/api/roles/role.gen.go",
outName: "Role",
outPkg: "roles",
},
{
os.Getenv("GEN_BASEPATH") + "/internal/gen/controller/api/resources/hosts/host_catalog.pb.go",
"AwsEc2HostCatalogDetails",
os.Getenv("GEN_BASEPATH") + "/api/hosts/awsec2_host_catalog.gen.go",
"AwsEc2HostCatalogDetails",
"hosts",
"",
"HostCatalog",
"AwsEc2HostCatalog",
templateTypeDetail,
inFile: os.Getenv("GEN_BASEPATH") + "/internal/gen/controller/api/resources/roles/role.pb.go",
inName: "Principal",
outFile: os.Getenv("GEN_BASEPATH") + "/api/roles/principal.gen.go",
outName: "Principal",
outPkg: "roles",
},
{
inFile: os.Getenv("GEN_BASEPATH") + "/internal/gen/controller/api/resources/hosts/host_catalog.pb.go",
inName: "StaticHostCatalogDetails",
outFile: os.Getenv("GEN_BASEPATH") + "/api/hosts/static_host_catalog.gen.go",
outName: "StaticHostCatalogDetails",
outPkg: "hosts",
parentName: "HostCatalog",
detailName: "StaticHostCatalog",
templateType: templateTypeDetail,
},
{
inFile: os.Getenv("GEN_BASEPATH") + "/internal/gen/controller/api/resources/hosts/host_catalog.pb.go",
inName: "AwsEc2HostCatalogDetails",
outFile: os.Getenv("GEN_BASEPATH") + "/api/hosts/awsec2_host_catalog.gen.go",
outName: "AwsEc2HostCatalogDetails",
outPkg: "hosts",
parentName: "HostCatalog",
detailName: "AwsEc2HostCatalog",
templateType: templateTypeDetail,
},
}
+5 -6
View File
@@ -38,6 +38,7 @@ func parsePBs() {
os.Exit(1)
}
inputStruct.nameJsonMap = make(map[string]string)
ast.Walk(visitFn(func(n ast.Node) {
spec, ok := n.(*ast.TypeSpec)
if !ok {
@@ -114,11 +115,6 @@ func parsePBs() {
var selectorExpr *ast.SelectorExpr
switch typ := field.Type.(type) {
case *ast.Ident:
// Id values are immutable and should always exist, so
// don't make it a pointer
if field.Names[0].Name != "Id" {
typ.Name = "*" + typ.Name
}
goto TAGMODIFY
case *ast.ArrayType:
goto TAGMODIFY
@@ -222,7 +218,10 @@ func parsePBs() {
}
TAGMODIFY:
st.Fields.List[i].Tag.Value = "`" + regex.FindString(st.Fields.List[i].Tag.Value) + "`"
tagString := regex.FindString(st.Fields.List[i].Tag.Value)
st.Fields.List[i].Tag.Value = "`" + tagString + "`"
tagString = strings.TrimSuffix(strings.TrimPrefix(tagString, `json:"`), `,omitempty"`)
inputStruct.nameJsonMap[strings.ToLower(field.Names[0].Name)] = tagString
}
}), inAst)
+5 -5
View File
@@ -37,11 +37,6 @@ var readFuncs = map[string][]*readInfo{
targetType: "users.User",
path: "users",
},
{
baseType: "Project",
targetType: "hosts.HostCatalog",
path: "host-catalogs",
},
{
baseType: "Project",
targetType: "groups.Group",
@@ -52,6 +47,11 @@ var readFuncs = map[string][]*readInfo{
targetType: "roles.Role",
path: "roles",
},
{
baseType: "Project",
targetType: "hosts.HostCatalog",
path: "host-catalogs",
},
},
}
+20 -3
View File
@@ -25,10 +25,12 @@ func writeStructTemplates() {
Name string
Package string
StructFields string
NameJsonMap map[string]string
}{
Name: inputStruct.outName,
Package: inputStruct.outPkg,
StructFields: inputStruct.structFields,
NameJsonMap: inputStruct.nameJsonMap,
})
case templateTypeDetail:
@@ -61,11 +63,12 @@ func writeStructTemplates() {
// TODO: Add documentation around SetDefault and how it behaves when the field corresponding to the provided key is already set.
var structTemplate = template.Must(template.New("").Parse(
`// Code generated by "make api"; DO NOT EDIT.
package {{ .Package }}
package {{ .Package }}
import (
"context"
"encoding/json"
"strings"
"github.com/fatih/structs"
@@ -82,11 +85,25 @@ type {{ .Name }} struct {
}
func (s *{{ .Name }}) SetDefault(key string) {
s.defaultFields = strutil.AppendIfMissing(s.defaultFields, key)
lowerKey := strings.ToLower(key)
validMap := {{ printf "%#v" .NameJsonMap }}
for k, v := range validMap {
if k == lowerKey || v == lowerKey {
s.defaultFields = strutil.AppendIfMissing(s.defaultFields, v)
return
}
}
}
func (s *{{ .Name }}) UnsetDefault(key string) {
s.defaultFields = strutil.StrListDelete(s.defaultFields, key)
lowerKey := strings.ToLower(key)
validMap := {{ printf "%#v" .NameJsonMap }}
for k, v := range validMap {
if k == lowerKey || v == lowerKey {
s.defaultFields = strutil.StrListDelete(s.defaultFields, v)
return
}
}
}
func (s {{ .Name }}) MarshalJSON() ([]byte, error) {
+26 -11
View File
@@ -32,25 +32,40 @@ func (r *Response) Decode(inStruct interface{}) (*Error, error) {
return nil, nil
}
// TODO Remove as we'll use the common err format for this
if r.resp.StatusCode == 403 {
// Nothing to be done
return &Error{
Status: http.StatusForbidden,
Message: "Forbidden",
}, nil
}
if inStruct == nil {
return nil, fmt.Errorf("nil value given to decode into and not a 204 response")
}
r.Body = new(bytes.Buffer)
if _, err := r.Body.ReadFrom(r.resp.Body); err != nil {
return nil, fmt.Errorf("error reading response body: %w", err)
apiErr := &Error{
Status: int32(r.resp.StatusCode),
}
if r.resp.Body != nil {
r.Body = new(bytes.Buffer)
if _, err := r.Body.ReadFrom(r.resp.Body); err != nil {
return nil, fmt.Errorf("error reading response body: %w", err)
}
dec := json.NewDecoder(bytes.NewReader(r.Body.Bytes()))
var apiErr Error
if r.resp.StatusCode >= 400 {
inStruct = &apiErr
}
if err := dec.Decode(inStruct); err != nil {
return nil, fmt.Errorf("error decoding response: %w; response was %s", err, r.Body.String())
if r.Body.Len() != 0 {
dec := json.NewDecoder(bytes.NewReader(r.Body.Bytes()))
if r.resp.StatusCode >= 400 {
inStruct = apiErr
}
if err := dec.Decode(inStruct); err != nil {
return nil, fmt.Errorf("error decoding response: %w; response was %s", err, r.Body.String())
}
}
}
if r.resp.StatusCode >= 400 {
return &apiErr, nil
return apiErr, nil
}
return nil, nil
+29 -15
View File
@@ -7,16 +7,17 @@ import (
"github.com/hashicorp/watchtower/api"
)
func (s Role) AddPrincipals(ctx context.Context, groups, users []string) (*Role, *api.Error, error) {
func (s Role) AddPrincipals(ctx context.Context, principalIds []string) (*Role, *api.Error, error) {
if s.Client == nil {
return nil, nil, fmt.Errorf("nil client in AddPrincipals request")
}
// We assume that the client provided has the org and optionally the project id of the request.
body := map[string]interface{}{
"group_ids": groups,
"user_ids": users,
"version": s.Version,
"version": s.Version,
}
if len(principalIds) > 0 {
body["principal_ids"] = principalIds
}
req, err := s.Client.NewRequest(ctx, "POST", fmt.Sprintf("roles/%s:add-principals", s.Id), body)
@@ -40,16 +41,20 @@ func (s Role) AddPrincipals(ctx context.Context, groups, users []string) (*Role,
return target, apiErr, nil
}
func (s Role) SetPrincipals(ctx context.Context, groups, users []string) (*Role, *api.Error, error) {
func (s Role) SetPrincipals(ctx context.Context, principalIds []string) (*Role, *api.Error, error) {
if s.Client == nil {
return nil, nil, fmt.Errorf("nil client in SetPrincipals request")
}
// We assume that the client provided has the org and optionally the project id of the request.
body := map[string]interface{}{
"group_ids": groups,
"user_ids": users,
"version": s.Version,
"version": s.Version,
}
if len(principalIds) > 0 {
body["principal_ids"] = principalIds
} else if principalIds != nil {
// In this function, a non-nil but empty list means clear out
body["principal_ids"] = nil
}
req, err := s.Client.NewRequest(ctx, "POST", fmt.Sprintf("roles/%s:set-principals", s.Id), body)
@@ -73,16 +78,17 @@ func (s Role) SetPrincipals(ctx context.Context, groups, users []string) (*Role,
return target, apiErr, nil
}
func (s Role) RemovePrincipals(ctx context.Context, groups, users []string) (*Role, *api.Error, error) {
func (s Role) RemovePrincipals(ctx context.Context, principalIds []string) (*Role, *api.Error, error) {
if s.Client == nil {
return nil, nil, fmt.Errorf("nil client in RemovePrincipals request")
}
// We assume that the client provided has the org and optionally the project id of the request.
body := map[string]interface{}{
"group_ids": groups,
"user_ids": users,
"version": s.Version,
"version": s.Version,
}
if len(principalIds) > 0 {
body["principal_ids"] = principalIds
}
req, err := s.Client.NewRequest(ctx, "POST", fmt.Sprintf("roles/%s:remove-principals", s.Id), body)
@@ -113,9 +119,11 @@ func (s Role) AddGrants(ctx context.Context, grants []string) (*Role, *api.Error
// We assume that the client provided has the org and optionally the project id of the request.
body := map[string]interface{}{
"grants": grants,
"version": s.Version,
}
if len(grants) > 0 {
body["grants"] = grants
}
req, err := s.Client.NewRequest(ctx, "POST", fmt.Sprintf("roles/%s:add-grants", s.Id), body)
if err != nil {
@@ -145,9 +153,13 @@ func (s Role) SetGrants(ctx context.Context, grants []string) (*Role, *api.Error
// We assume that the client provided has the org and optionally the project id of the request.
body := map[string]interface{}{
"grants": grants,
"version": s.Version,
}
if len(grants) > 0 {
body["grants"] = grants
} else if grants != nil {
body["grants"] = nil
}
req, err := s.Client.NewRequest(ctx, "POST", fmt.Sprintf("roles/%s:set-grants", s.Id), body)
if err != nil {
@@ -177,9 +189,11 @@ func (s Role) RemoveGrants(ctx context.Context, grants []string) (*Role, *api.Er
// We assume that the client provided has the org and optionally the project id of the request.
body := map[string]interface{}{
"grants": grants,
"version": s.Version,
}
if len(grants) > 0 {
body["grants"] = grants
}
req, err := s.Client.NewRequest(ctx, "POST", fmt.Sprintf("roles/%s:remove-grants", s.Id), body)
if err != nil {
+61
View File
@@ -0,0 +1,61 @@
// Code generated by "make api"; DO NOT EDIT.
package roles
import (
"encoding/json"
"strings"
"github.com/fatih/structs"
"github.com/hashicorp/watchtower/api"
"github.com/hashicorp/watchtower/api/internal/strutil"
)
type Principal struct {
Client *api.Client `json:"-"`
defaultFields []string
// The ID of the principal.
// Output only.
Id string `json:"id,omitempty"`
// The type of the principal.
// Output only.
Type string `json:"type,omitempty"`
// The scope ID of the principal.
// Output only.
ScopeId string `json:"scope_id,omitempty"`
}
func (s *Principal) SetDefault(key string) {
lowerKey := strings.ToLower(key)
validMap := map[string]string{"id": "id", "scopeid": "scope_id", "type": "type"}
for k, v := range validMap {
if k == lowerKey || v == lowerKey {
s.defaultFields = strutil.AppendIfMissing(s.defaultFields, v)
return
}
}
}
func (s *Principal) UnsetDefault(key string) {
lowerKey := strings.ToLower(key)
validMap := map[string]string{"id": "id", "scopeid": "scope_id", "type": "type"}
for k, v := range validMap {
if k == lowerKey || v == lowerKey {
s.defaultFields = strutil.StrListDelete(s.defaultFields, v)
return
}
}
}
func (s Principal) MarshalJSON() ([]byte, error) {
m := structs.Map(s)
if m == nil {
m = make(map[string]interface{})
}
for _, k := range s.defaultFields {
m[k] = nil
}
return json.Marshal(m)
}
+23 -7
View File
@@ -3,6 +3,7 @@ package roles
import (
"encoding/json"
"strings"
"time"
"github.com/fatih/structs"
@@ -40,13 +41,14 @@ type Role struct {
// The version can be used in subsiquent write requests to ensure this resource
// has not changed and to fail the write if it has.
// Output only.
Version *uint32 `json:"version,omitempty"`
// The principals that are assigned this role.
Version uint32 `json:"version,omitempty"`
// The IDs (only) of principals that are assigned to this role.
// Output only.
UserIds []string `json:"user_ids,omitempty"`
PrincipalIds []string `json:"principal_ids,omitempty"`
// The principals that are assigned to this role.
// Output only.
GroupIds []string `json:"group_ids,omitempty"`
// The grants that this role provides for it's principals.
Principals []*Principal `json:"principals,omitempty"`
// The grants that this role provides for its principals.
// Output only.
Grants []string `json:"grants,omitempty"`
// The canonical version of the grants in the grants field with the same index.
@@ -58,11 +60,25 @@ type Role struct {
}
func (s *Role) SetDefault(key string) {
s.defaultFields = strutil.AppendIfMissing(s.defaultFields, key)
lowerKey := strings.ToLower(key)
validMap := map[string]string{"createdtime": "created_time", "description": "description", "disabled": "disabled", "grants": "grants", "grantscanonical": "grants_canonical", "grantscopeid": "grant_scope_id", "grantsjson": "grants_json", "id": "id", "name": "name", "principalids": "principal_ids", "principals": "principals", "updatedtime": "updated_time", "version": "version"}
for k, v := range validMap {
if k == lowerKey || v == lowerKey {
s.defaultFields = strutil.AppendIfMissing(s.defaultFields, v)
return
}
}
}
func (s *Role) UnsetDefault(key string) {
s.defaultFields = strutil.StrListDelete(s.defaultFields, key)
lowerKey := strings.ToLower(key)
validMap := map[string]string{"createdtime": "created_time", "description": "description", "disabled": "disabled", "grants": "grants", "grantscanonical": "grants_canonical", "grantscopeid": "grant_scope_id", "grantsjson": "grants_json", "id": "id", "name": "name", "principalids": "principal_ids", "principals": "principals", "updatedtime": "updated_time", "version": "version"}
for k, v := range validMap {
if k == lowerKey || v == lowerKey {
s.defaultFields = strutil.StrListDelete(s.defaultFields, v)
return
}
}
}
func (s Role) MarshalJSON() ([]byte, error) {
+86 -56
View File
@@ -6,6 +6,7 @@ import (
"net/http"
"testing"
"github.com/hashicorp/vault/sdk/helper/strutil"
"github.com/hashicorp/watchtower/api"
"github.com/hashicorp/watchtower/api/groups"
"github.com/hashicorp/watchtower/api/roles"
@@ -27,7 +28,7 @@ type roleCrud interface {
}
func TestCustom(t *testing.T) {
tc := controller.NewTestController(t, nil)
tc := controller.NewTestController(t, &controller.TestControllerOpts{DisableAuthorizationFailures: true})
defer tc.Shutdown()
client := tc.Client()
@@ -56,6 +57,22 @@ func TestCustom(t *testing.T) {
},
}
hasPrincipal := func(role *roles.Role, principalId string) bool {
var foundInPrincipals bool
var foundInPrincipalIds bool
for _, v := range role.Principals {
if v.Id == principalId {
foundInPrincipals = true
}
}
for _, v := range role.PrincipalIds {
if v == principalId {
foundInPrincipalIds = true
}
}
return foundInPrincipals && foundInPrincipalIds
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
require := require.New(t)
@@ -70,63 +87,52 @@ func TestCustom(t *testing.T) {
require.Nil(apiErr)
require.NotNil(r)
updatedRole, apiErr, err := r.AddPrincipals(ctx, []string{g.Id}, nil)
updatedRole, apiErr, err := r.AddPrincipals(ctx, []string{g.Id})
require.NoError(err)
require.Nil(apiErr, "Got error ", errorMessage(apiErr))
assert.Equal(t, *updatedRole.Version, (*r.Version)+1)
assert.Contains(t, updatedRole.GroupIds, g.Id)
assert.Empty(t, updatedRole.UserIds)
require.Nil(apiErr, "Got error ", apiErr)
assert.Equal(t, updatedRole.Version, r.Version+1)
assert.True(t, hasPrincipal(updatedRole, g.Id))
r = updatedRole
updatedRole, apiErr, err = r.SetPrincipals(ctx, nil, []string{user.Id})
updatedRole, apiErr, err = r.SetPrincipals(ctx, []string{user.Id})
require.NoError(err)
require.Nil(apiErr, "Got error ", errorMessage(apiErr))
assert.Equal(t, *updatedRole.Version, (*r.Version)+1)
assert.Empty(t, updatedRole.GroupIds)
assert.Contains(t, updatedRole.UserIds, user.Id)
require.Nil(apiErr, "Got error ", apiErr)
assert.Equal(t, updatedRole.Version, r.Version+1)
assert.True(t, hasPrincipal(updatedRole, user.Id))
r = updatedRole
updatedRole, apiErr, err = r.RemovePrincipals(ctx, nil, []string{user.Id})
updatedRole, apiErr, err = r.RemovePrincipals(ctx, []string{user.Id})
require.NoError(err)
require.Nil(apiErr, "Got error ", errorMessage(apiErr))
assert.Equal(t, *updatedRole.Version, (*r.Version)+1)
assert.Empty(t, updatedRole.GroupIds)
assert.Empty(t, updatedRole.UserIds)
require.Nil(apiErr, "Got error ", apiErr)
assert.Equal(t, updatedRole.Version, r.Version+1)
assert.Empty(t, updatedRole.Principals)
r = updatedRole
updatedRole, apiErr, err = r.AddGrants(ctx, []string{"id=*;actions=read"})
require.NoError(err)
require.Nil(apiErr, "Got error ", errorMessage(apiErr))
assert.Equal(t, *updatedRole.Version, (*r.Version)+1)
require.Nil(apiErr, "Got error ", apiErr)
assert.Equal(t, updatedRole.Version, r.Version+1)
assert.Contains(t, updatedRole.Grants, "id=*;actions=read")
r = updatedRole
updatedRole, apiErr, err = r.SetGrants(ctx, []string{"id=*;actions=*"})
require.NoError(err)
require.Nil(apiErr, "Got error ", errorMessage(apiErr))
assert.Equal(t, *updatedRole.Version, (*r.Version)+1)
require.Nil(apiErr, "Got error ", apiErr)
assert.Equal(t, updatedRole.Version, r.Version+1)
assert.Contains(t, updatedRole.Grants, "id=*;actions=*")
r = updatedRole
updatedRole, apiErr, err = r.RemoveGrants(ctx, []string{"id=*;actions=*"})
require.NoError(err)
require.Nil(apiErr, "Got error ", errorMessage(apiErr))
assert.Equal(t, *updatedRole.Version, (*r.Version)+1)
require.Nil(apiErr, "Got error ", apiErr)
assert.Equal(t, updatedRole.Version, r.Version+1)
assert.Empty(t, updatedRole.Grants)
})
}
}
func errorMessage(in *api.Error) string {
if in == nil {
return ""
}
return *in.Message
}
func TestRole_List(t *testing.T) {
assert := assert.New(t)
tc := controller.NewTestController(t, nil)
tc := controller.NewTestController(t, &controller.TestControllerOpts{DisableAuthorizationFailures: true})
defer tc.Shutdown()
client := tc.Client()
@@ -153,12 +159,19 @@ func TestRole_List(t *testing.T) {
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
ctx := context.Background()
pl, apiErr, err := tc.scope.ListRoles(ctx)
assert.NoError(err)
p1, apiErr, err := tc.scope.ListRoles(ctx)
require.NoError(err)
assert.Nil(apiErr)
assert.Empty(pl)
var defaultRoleIds []string
if tc.name == "org" {
require.True(2 == len(p1))
defaultRoleIds = []string{p1[0].Id, p1[1].Id}
} else {
require.Empty(p1)
}
var expected []*roles.Role
for i := 0; i < 10; i++ {
@@ -166,21 +179,35 @@ func TestRole_List(t *testing.T) {
}
expected[0], apiErr, err = tc.scope.CreateRole(ctx, expected[0])
assert.NoError(err)
require.NoError(err)
assert.Nil(apiErr)
pl, apiErr, err = tc.scope.ListRoles(ctx)
p2, apiErr, err := tc.scope.ListRoles(ctx)
assert.NoError(err)
assert.Nil(apiErr)
assert.ElementsMatch(comparableSlice(expected[:1]), comparableSlice(pl))
var p2ForComparison []*roles.Role
for _, v := range p2 {
if !strutil.StrListContains(defaultRoleIds, v.Id) {
p2ForComparison = append(p2ForComparison, v)
}
}
assert.ElementsMatch(comparableSlice(expected[:1]), comparableSlice(p2ForComparison))
for i := 1; i < 10; i++ {
expected[i], apiErr, err = tc.scope.CreateRole(ctx, expected[i])
assert.NoError(err)
assert.Nil(apiErr)
}
pl, apiErr, err = tc.scope.ListRoles(ctx)
assert.ElementsMatch(comparableSlice(expected), comparableSlice(pl))
p3, apiErr, err := tc.scope.ListRoles(ctx)
require.NoError(err)
assert.Nil(apiErr)
var p3ForComparison []*roles.Role
for _, v := range p3 {
if !strutil.StrListContains(defaultRoleIds, v.Id) {
p3ForComparison = append(p3ForComparison, v)
}
}
assert.ElementsMatch(comparableSlice(expected), comparableSlice(p3ForComparison))
})
}
}
@@ -202,7 +229,7 @@ func comparableSlice(in []*roles.Role) []roles.Role {
}
func TestRole_Crud(t *testing.T) {
tc := controller.NewTestController(t, nil)
tc := controller.NewTestController(t, &controller.TestControllerOpts{DisableAuthorizationFailures: true})
defer tc.Shutdown()
client := tc.Client()
@@ -217,8 +244,8 @@ func TestRole_Crud(t *testing.T) {
checkRole := func(step string, g *roles.Role, apiErr *api.Error, err error, wantedName string) {
assert := assert.New(t)
assert.NoError(err, step)
if !assert.Nil(apiErr, step) && apiErr.Message != nil {
t.Errorf("ApiError message: %q", *apiErr.Message)
if !assert.Nil(apiErr, step) && apiErr.Message != "" {
t.Errorf("ApiError message: %q", apiErr.Message)
}
assert.NotNil(g, "returned no resource", step)
gotName := ""
@@ -244,6 +271,7 @@ func TestRole_Crud(t *testing.T) {
for _, tt := range cases {
t.Run(tt.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
g, apiErr, err := tt.scope.CreateRole(tc.Context(), &roles.Role{Name: api.String("foo")})
checkRole("create", g, apiErr, err, "foo")
@@ -261,19 +289,20 @@ func TestRole_Crud(t *testing.T) {
checkRole("update", g, apiErr, err, "")
existed, apiErr, err := tt.scope.DeleteRole(tc.Context(), g)
assert.NoError(t, err)
assert.True(t, existed, "Expected existing user when deleted, but it wasn't.")
require.NoError(err)
assert.Nil(apiErr)
assert.True(existed, "Expected existing user when deleted, but it wasn't.")
existed, apiErr, err = tt.scope.DeleteRole(tc.Context(), g)
assert.NoError(t, err)
assert.False(t, existed, "Expected user to not exist when deleted, but it did.")
require.NoError(err)
assert.Nil(apiErr)
assert.False(existed, "Expected user to not exist when deleted, but it did.")
})
}
}
func TestRole_Errors(t *testing.T) {
assert := assert.New(t)
tc := controller.NewTestController(t, nil)
tc := controller.NewTestController(t, &controller.TestControllerOpts{DisableAuthorizationFailures: true})
defer tc.Shutdown()
ctx := tc.Context()
@@ -302,30 +331,31 @@ func TestRole_Errors(t *testing.T) {
for _, tt := range cases {
t.Run(tt.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
u, apiErr, err := tt.scope.CreateRole(ctx, &roles.Role{Name: api.String("first")})
assert.NoError(err)
require.NoError(err)
assert.Nil(apiErr)
assert.NotNil(u)
// Create another resource with the same name.
_, apiErr, err = tt.scope.CreateRole(ctx, &roles.Role{Name: api.String("first")})
assert.NoError(err)
require.NoError(err)
assert.NotNil(apiErr)
_, apiErr, err = tt.scope.ReadRole(ctx, &roles.Role{Id: iam.RolePrefix + "_doesntexis"})
assert.NoError(err)
require.NoError(err)
assert.NotNil(apiErr)
assert.EqualValues(*apiErr.Status, http.StatusNotFound)
assert.EqualValues(http.StatusNotFound, apiErr.Status)
_, apiErr, err = tt.scope.ReadRole(ctx, &roles.Role{Id: "invalid id"})
assert.NoError(err)
require.NoError(err)
assert.NotNil(apiErr)
assert.EqualValues(*apiErr.Status, http.StatusBadRequest)
assert.EqualValues(http.StatusBadRequest, apiErr.Status)
_, apiErr, err = tt.scope.UpdateRole(ctx, &roles.Role{Id: u.Id})
assert.NoError(err)
require.NoError(err)
assert.NotNil(apiErr)
assert.EqualValues(*apiErr.Status, http.StatusBadRequest)
assert.EqualValues(http.StatusBadRequest, apiErr.Status)
})
}
}
+54
View File
@@ -0,0 +1,54 @@
package scopes
import (
"context"
"fmt"
"github.com/hashicorp/watchtower/api"
"github.com/hashicorp/watchtower/api/authtokens"
)
// TODO: This will need to be changed when we add Auth Method API to watchtower. We'll also need a better
// way to handle different auth method types.
func (s Org) Authenticate(ctx context.Context, authMethodId, name, password string) (*authtokens.AuthToken, *api.Error, error) {
if s.Client == nil {
return nil, nil, fmt.Errorf("nil client in Authenticate request")
}
if s.Id == "" {
// Assume the client has been configured with org already and
// move on
} else {
// If it's explicitly set here, override anything that might be in the
// client
ctx = context.WithValue(ctx, "org", s.Id)
}
reqBody := map[string]interface{}{
"credentials": map[string]string{
"name": name,
"password": password,
},
}
req, err := s.Client.NewRequest(ctx, "POST", fmt.Sprintf("auth-methods/%s:authenticate", authMethodId), reqBody)
if err != nil {
return nil, nil, fmt.Errorf("error creating Authenticate request: %w", err)
}
resp, err := s.Client.Do(req)
if err != nil {
return nil, nil, fmt.Errorf("error performing client request during Authenticate call: %w", err)
}
target := new(authtokens.AuthToken)
apiErr, err := resp.Decode(target)
if err != nil {
return nil, nil, fmt.Errorf("error decoding Authenticate response: %w", err)
}
if target.Token != "" {
s.Client.SetToken(target.Token)
}
return target, apiErr, nil
}
+34
View File
@@ -0,0 +1,34 @@
package scopes_test
import (
"context"
"net/http"
"testing"
"github.com/hashicorp/watchtower/api/scopes"
"github.com/hashicorp/watchtower/internal/servers/controller"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestAuthenticate(t *testing.T) {
assert := assert.New(t)
tc := controller.NewTestController(t, nil)
defer tc.Shutdown()
client := tc.Client()
org := &scopes.Org{
Client: client,
}
ctx := context.Background()
tok, apiErr, err := org.Authenticate(ctx, "am_anything", "admin", "hunter2")
assert.NoError(err)
assert.Nil(apiErr)
assert.NotNil(tok)
_, apiErr, err = org.Authenticate(ctx, "am_anything", "wrong", "wrong")
assert.NoError(err)
require.NotNil(t, apiErr)
assert.EqualValuesf(http.StatusUnauthorized, apiErr.Status, "Expected unauthenticated, got %q", apiErr.Message)
}
+17 -2
View File
@@ -3,6 +3,7 @@ package scopes
import (
"encoding/json"
"strings"
"time"
"github.com/fatih/structs"
@@ -32,11 +33,25 @@ type Org struct {
}
func (s *Org) SetDefault(key string) {
s.defaultFields = strutil.AppendIfMissing(s.defaultFields, key)
lowerKey := strings.ToLower(key)
validMap := map[string]string{"createdtime": "created_time", "description": "description", "id": "id", "name": "name", "updatedtime": "updated_time"}
for k, v := range validMap {
if k == lowerKey || v == lowerKey {
s.defaultFields = strutil.AppendIfMissing(s.defaultFields, v)
return
}
}
}
func (s *Org) UnsetDefault(key string) {
s.defaultFields = strutil.StrListDelete(s.defaultFields, key)
lowerKey := strings.ToLower(key)
validMap := map[string]string{"createdtime": "created_time", "description": "description", "id": "id", "name": "name", "updatedtime": "updated_time"}
for k, v := range validMap {
if k == lowerKey || v == lowerKey {
s.defaultFields = strutil.StrListDelete(s.defaultFields, v)
return
}
}
}
func (s Org) MarshalJSON() ([]byte, error) {
+17 -2
View File
@@ -3,6 +3,7 @@ package scopes
import (
"encoding/json"
"strings"
"time"
"github.com/fatih/structs"
@@ -34,11 +35,25 @@ type Project struct {
}
func (s *Project) SetDefault(key string) {
s.defaultFields = strutil.AppendIfMissing(s.defaultFields, key)
lowerKey := strings.ToLower(key)
validMap := map[string]string{"createdtime": "created_time", "description": "description", "disabled": "disabled", "id": "id", "name": "name", "updatedtime": "updated_time"}
for k, v := range validMap {
if k == lowerKey || v == lowerKey {
s.defaultFields = strutil.AppendIfMissing(s.defaultFields, v)
return
}
}
}
func (s *Project) UnsetDefault(key string) {
s.defaultFields = strutil.StrListDelete(s.defaultFields, key)
lowerKey := strings.ToLower(key)
validMap := map[string]string{"createdtime": "created_time", "description": "description", "disabled": "disabled", "id": "id", "name": "name", "updatedtime": "updated_time"}
for k, v := range validMap {
if k == lowerKey || v == lowerKey {
s.defaultFields = strutil.StrListDelete(s.defaultFields, v)
return
}
}
}
func (s Project) MarshalJSON() ([]byte, error) {
+2 -2
View File
@@ -133,10 +133,10 @@ func TestProject_Errors(t *testing.T) {
assert.NoError(err)
// TODO: Should this be nil instead of just a Project that has no values set
assert.NotNil(apiErr)
assert.EqualValues(*apiErr.Status, http.StatusNotFound)
assert.EqualValues(apiErr.Status, http.StatusNotFound)
_, apiErr, err = org.ReadProject(ctx, &scopes.Project{Id: "invalid id"})
assert.NoError(err)
assert.NotNil(apiErr)
assert.EqualValues(*apiErr.Status, http.StatusBadRequest)
assert.EqualValues(apiErr.Status, http.StatusBadRequest)
}
+41 -41
View File
@@ -177,47 +177,6 @@ func (s Org) ReadUser(ctx context.Context, r *users.User) (*users.User, *api.Err
return target, apiErr, nil
}
func (s Project) ReadHostCatalog(ctx context.Context, r *hosts.HostCatalog) (*hosts.HostCatalog, *api.Error, error) {
if s.Client == nil {
return nil, nil, fmt.Errorf("nil client in ReadHostCatalog request")
}
if s.Id == "" {
// Assume the client has been configured with project already and move
// on
} else {
// If it's explicitly set here, override anything that might be in the
// client
ctx = context.WithValue(ctx, "project", s.Id)
}
if r.Id == "" {
return nil, nil, fmt.Errorf("empty hosts.HostCatalog ID field in ReadHostCatalog request")
}
req, err := s.Client.NewRequest(ctx, "GET", fmt.Sprintf("%s/%s", "host-catalogs", r.Id), r)
if err != nil {
return nil, nil, fmt.Errorf("error creating ReadHostCatalog request: %w", err)
}
resp, err := s.Client.Do(req)
if err != nil {
return nil, nil, fmt.Errorf("error performing client request during ReadHostCatalog call: %w", err)
}
target := new(hosts.HostCatalog)
apiErr, err := resp.Decode(target)
if err != nil {
return nil, nil, fmt.Errorf("error decoding ReadHostCatalog repsonse: %w", err)
}
target.Client = s.Client
return target, apiErr, nil
}
func (s Project) ReadGroup(ctx context.Context, r *groups.Group) (*groups.Group, *api.Error, error) {
if s.Client == nil {
return nil, nil, fmt.Errorf("nil client in ReadGroup request")
@@ -299,3 +258,44 @@ func (s Project) ReadRole(ctx context.Context, r *roles.Role) (*roles.Role, *api
return target, apiErr, nil
}
func (s Project) ReadHostCatalog(ctx context.Context, r *hosts.HostCatalog) (*hosts.HostCatalog, *api.Error, error) {
if s.Client == nil {
return nil, nil, fmt.Errorf("nil client in ReadHostCatalog request")
}
if s.Id == "" {
// Assume the client has been configured with project already and move
// on
} else {
// If it's explicitly set here, override anything that might be in the
// client
ctx = context.WithValue(ctx, "project", s.Id)
}
if r.Id == "" {
return nil, nil, fmt.Errorf("empty hosts.HostCatalog ID field in ReadHostCatalog request")
}
req, err := s.Client.NewRequest(ctx, "GET", fmt.Sprintf("%s/%s", "host-catalogs", r.Id), r)
if err != nil {
return nil, nil, fmt.Errorf("error creating ReadHostCatalog request: %w", err)
}
resp, err := s.Client.Do(req)
if err != nil {
return nil, nil, fmt.Errorf("error performing client request during ReadHostCatalog call: %w", err)
}
target := new(hosts.HostCatalog)
apiErr, err := resp.Decode(target)
if err != nil {
return nil, nil, fmt.Errorf("error decoding ReadHostCatalog repsonse: %w", err)
}
target.Client = s.Client
return target, apiErr, nil
}
+17 -2
View File
@@ -3,6 +3,7 @@ package users
import (
"encoding/json"
"strings"
"time"
"github.com/fatih/structs"
@@ -34,11 +35,25 @@ type User struct {
}
func (s *User) SetDefault(key string) {
s.defaultFields = strutil.AppendIfMissing(s.defaultFields, key)
lowerKey := strings.ToLower(key)
validMap := map[string]string{"createdtime": "created_time", "description": "description", "disabled": "disabled", "id": "id", "name": "name", "updatedtime": "updated_time"}
for k, v := range validMap {
if k == lowerKey || v == lowerKey {
s.defaultFields = strutil.AppendIfMissing(s.defaultFields, v)
return
}
}
}
func (s *User) UnsetDefault(key string) {
s.defaultFields = strutil.StrListDelete(s.defaultFields, key)
lowerKey := strings.ToLower(key)
validMap := map[string]string{"createdtime": "created_time", "description": "description", "disabled": "disabled", "id": "id", "name": "name", "updatedtime": "updated_time"}
for k, v := range validMap {
if k == lowerKey || v == lowerKey {
s.defaultFields = strutil.StrListDelete(s.defaultFields, v)
return
}
}
}
func (s User) MarshalJSON() ([]byte, error) {
+13 -8
View File
@@ -12,6 +12,7 @@ import (
"github.com/hashicorp/watchtower/internal/iam"
"github.com/hashicorp/watchtower/internal/servers/controller"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestUsers_List(t *testing.T) {
@@ -50,6 +51,8 @@ func TestUsers_List(t *testing.T) {
assert.Nil(apiErr)
}
ul, apiErr, err = org.ListUsers(ctx)
require.NoError(t, err)
assert.Nil(apiErr)
assert.ElementsMatch(comparableSlice(expected), comparableSlice(ul))
}
@@ -81,8 +84,8 @@ func TestUser_Crud(t *testing.T) {
checkUser := func(step string, u *users.User, apiErr *api.Error, err error, wantedName string) {
assert := assert.New(t)
assert.NoError(err, step)
if !assert.Nil(apiErr, step) && apiErr.Message != nil {
t.Errorf("ApiError message: %q", *apiErr.Message)
if !assert.Nil(apiErr, step) && apiErr.Message != "" {
t.Errorf("ApiError message: %q", apiErr.Message)
}
assert.NotNil(u, "returned no resource", step)
gotName := ""
@@ -108,12 +111,14 @@ func TestUser_Crud(t *testing.T) {
u, apiErr, err = org.UpdateUser(tc.Context(), u)
checkUser("update", u, apiErr, err, "")
existed, apiErr, err := org.DeleteUser(tc.Context(), u)
assert.NoError(t, err)
existed, _, err := org.DeleteUser(tc.Context(), u)
require.NoError(t, err)
assert.Nil(t, apiErr)
assert.True(t, existed, "Expected existing user when deleted, but it wasn't.")
existed, apiErr, err = org.DeleteUser(tc.Context(), u)
assert.NoError(t, err)
require.NoError(t, err)
assert.Nil(t, apiErr)
assert.False(t, existed, "Expected user to not exist when deleted, but it did.")
}
@@ -141,15 +146,15 @@ func TestUser_Errors(t *testing.T) {
_, apiErr, err = org.ReadUser(ctx, &users.User{Id: iam.UserPrefix + "_doesntexis"})
assert.NoError(err)
assert.NotNil(apiErr)
assert.EqualValues(*apiErr.Status, http.StatusNotFound)
assert.EqualValues(apiErr.Status, http.StatusNotFound)
_, apiErr, err = org.ReadUser(ctx, &users.User{Id: "invalid id"})
assert.NoError(err)
assert.NotNil(apiErr)
assert.EqualValues(*apiErr.Status, http.StatusBadRequest)
assert.EqualValues(apiErr.Status, http.StatusBadRequest)
_, apiErr, err = org.UpdateUser(ctx, &users.User{Id: u.Id})
assert.NoError(err)
assert.NotNil(apiErr)
assert.EqualValues(*apiErr.Status, http.StatusBadRequest)
assert.EqualValues(apiErr.Status, http.StatusBadRequest)
}
+4
View File
@@ -9,6 +9,10 @@ import "time"
// import issues. These values should only ever be set at startup, but simply
// available to reference from anywhere.
const (
ContextUserIdValue = "wt_user_id"
)
var (
// DefaultMaxRequestDuration is the amount of time we'll wait for a request
DefaultMaxRequestDuration = 90 * time.Second
+5
View File
@@ -17,6 +17,7 @@ require (
github.com/go-openapi/swag v0.19.9 // indirect
github.com/go-openapi/validate v0.19.8 // indirect
github.com/go-swagger/go-swagger v0.23.0
github.com/go-test/deep v1.0.3 // indirect
github.com/golang-migrate/migrate/v4 v4.11.0
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe
github.com/golang/protobuf v1.4.2
@@ -29,6 +30,7 @@ require (
github.com/hashicorp/go-hclog v0.14.1
github.com/hashicorp/go-kms-wrapping v0.5.10
github.com/hashicorp/go-multierror v1.1.0
github.com/hashicorp/go-plugin v1.2.0 // indirect
github.com/hashicorp/go-retryablehttp v0.6.6
github.com/hashicorp/go-rootcerts v1.0.2
github.com/hashicorp/go-sockaddr v1.0.2
@@ -44,6 +46,7 @@ require (
github.com/mattn/go-colorable v0.1.6
github.com/mitchellh/cli v1.1.1
github.com/mitchellh/go-homedir v1.1.0
github.com/mitchellh/go-wordwrap v1.0.0
github.com/mitchellh/gox v1.0.1
github.com/mitchellh/mapstructure v1.3.2
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
@@ -57,7 +60,9 @@ require (
github.com/ryanuber/go-glob v1.0.0
github.com/spf13/viper v1.6.3 // indirect
github.com/stretchr/testify v1.6.1
github.com/zalando/go-keyring v0.1.0
go.mongodb.org/mongo-driver v1.3.2 // indirect
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37
golang.org/x/net v0.0.0-20200519113804-d87ec0cfa476 // indirect
golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f // indirect
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1
+13
View File
@@ -248,6 +248,8 @@ github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7Do
github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/cznic/mathutil v0.0.0-20180504122225-ca4c9f2c1369/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM=
github.com/danieljoos/wincred v1.0.2 h1:zf4bhty2iLuwgjgpraD2E9UbvO+fe54XXGJbOwe23fU=
github.com/danieljoos/wincred v1.0.2/go.mod h1:SnuYRW9lp1oJrZX/dXJqr0cPK5gYXqx3EJbmjhLdK9U=
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=
@@ -430,6 +432,8 @@ github.com/go-test/deep v1.0.1/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3a
github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/go-test/deep v1.0.2 h1:onZX1rnHT3Wv6cqNgYyFOOlgVKJrksuCMCRvJStbMYw=
github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/go-yaml/yaml v2.1.0+incompatible h1:RYi2hDdss1u4YE7GwixGzWwVo47T8UQwnTLB6vQiq+o=
github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0=
github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0=
@@ -469,6 +473,8 @@ github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY9
github.com/gocql/gocql v0.0.0-20190301043612-f6df8288f9b4/go.mod h1:4Fw1eo5iaEhDUs8XyuhSVCVy52Jq3L+/3GJgYkwc+/0=
github.com/gocql/gocql v0.0.0-20190402132108-0e1d5de854df h1:fwXmhM0OqixzJDOGgTSyNH9eEDij9uGTXwsyWXvyR0A=
github.com/gocql/gocql v0.0.0-20190402132108-0e1d5de854df/go.mod h1:4Fw1eo5iaEhDUs8XyuhSVCVy52Jq3L+/3GJgYkwc+/0=
github.com/godbus/dbus v4.1.0+incompatible h1:WqqLRTsQic3apZUK9qC5sGNfXthmPXzUZ7nQPrNITa4=
github.com/godbus/dbus v4.1.0+incompatible/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE=
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
@@ -639,6 +645,8 @@ github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+
github.com/hashicorp/go-plugin v1.0.0/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY=
github.com/hashicorp/go-plugin v1.0.1 h1:4OtAfUGbnKC6yS48p0CtMX2oFYtzFZVv6rok3cRWgnE=
github.com/hashicorp/go-plugin v1.0.1/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY=
github.com/hashicorp/go-plugin v1.2.0 h1:CUfYokW0EJNDcGecVrHZK//Cp1GFlHwoqtcUIEiU6BY=
github.com/hashicorp/go-plugin v1.2.0/go.mod h1:F9eH4LrE/ZsRdbwhfjs9k9HoDUwAHnYtXdgmf1AVNs0=
github.com/hashicorp/go-raftchunking v0.6.3-0.20191002164813-7e9e8525653a h1:FmnBDwGwlTgugDGbVxwV8UavqSMACbGrUpfc98yFLR4=
github.com/hashicorp/go-raftchunking v0.6.3-0.20191002164813-7e9e8525653a/go.mod h1:xbXnmKqX9/+RhPkJ4zrEx4738HacP72aaUPlT2RZ4sU=
github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
@@ -837,6 +845,7 @@ github.com/jefferai/jsonx v1.0.0 h1:Xoz0ZbmkpBvED5W9W1B5B/zc3Oiq7oXqiW7iRV3B6EI=
github.com/jefferai/jsonx v1.0.0/go.mod h1:OGmqmi2tTeI/PS+qQfBDToLHHJIy/RMp24fPo8vFvoQ=
github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74=
github.com/jhump/protoreflect v1.6.2-0.20200602154950-9a9113f80b57 h1:DDbkVWVTpzxHbD80e2zpbczB+gkTWI1w2gSeL+viRhc=
github.com/jhump/protoreflect v1.6.2-0.20200602154950-9a9113f80b57/go.mod h1:RZkzh7Hi9J7qT/sPlWnJ/UwZqCJvciFxKDA0UCeltSM=
github.com/jinzhu/gorm v1.9.12 h1:Drgk1clyWT9t9ERbzHza6Mj/8FY/CqMyVzOiHviMo6Q=
@@ -982,6 +991,7 @@ github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
github.com/mitchellh/gox v1.0.1 h1:x0jD3dcHk9a9xPSDN6YEL4xL6Qz0dvNYm8yZqui5chI=
@@ -1256,6 +1266,8 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/zalando/go-keyring v0.1.0 h1:ffq972Aoa4iHNzBlUHgK5Y+k8+r/8GvcGd80/OFZb/k=
github.com/zalando/go-keyring v0.1.0/go.mod h1:RaxNwUITJaHVdQ0VC7pELPZ3tOWn13nr0gZMZEhpVU0=
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
@@ -1367,6 +1379,7 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/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-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180801234040-f4c29de78a2a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+36
View File
@@ -18,6 +18,7 @@ import (
"github.com/mitchellh/cli"
"github.com/pkg/errors"
"github.com/posener/complete"
"github.com/zalando/go-keyring"
)
const (
@@ -26,6 +27,8 @@ const (
// NotSetValue is a flag value for a not-set value
NotSetValue = "(not set)"
envTokenName = "WATCHTOWER_TOKEN_NAME"
)
// reRemoveWhitespace is a regular expression for stripping whitespace from
@@ -53,6 +56,7 @@ type Command struct {
flagFormat string
flagField string
FlagTokenName string
flagOutputCurlString bool
client *api.Client
@@ -161,6 +165,26 @@ func (c *Command) Client() (*api.Client, error) {
c.client.SetMaxRetries(0)
}
if c.client.Token() == "" {
tokenName := "default"
if c.FlagTokenName != "" {
tokenName = c.FlagTokenName
}
if tokenName != "none" {
token, err := keyring.Get("HashiCorp Watchtower Auth Token", tokenName)
if err != nil {
if err == keyring.ErrNotFound {
c.UI.Info("No saved credential found, continuing without")
} else {
c.UI.Error(fmt.Sprintf("Error reading auth token from system credential store: %s", err))
}
}
if token != "" {
c.client.SetToken(token)
}
}
}
return c.client, nil
}
@@ -169,6 +193,7 @@ type FlagSetBit uint
const (
FlagSetNone FlagSetBit = 1 << iota
FlagSetHTTP
FlagSetClient
FlagSetOutputField
FlagSetOutputFormat
)
@@ -274,6 +299,17 @@ func (c *Command) FlagSet(bit FlagSetBit) *FlagSets {
"is highly discouraged as it decreases the security of data " +
"transmissions to and from the Watchtower server.",
})
}
if bit&FlagSetClient != 0 {
f := set.NewFlagSet("Client Options")
f.StringVar(&StringVar{
Name: "token-name",
Target: &c.FlagTokenName,
EnvVar: envTokenName,
Usage: "If specified, the given value will be used as the name when storing the token in the system credential store. This can allow switching user identities for different commands.",
})
f.BoolVar(&BoolVar{
Name: "output-curl-string",
+64 -1
View File
@@ -3,11 +3,15 @@ package base
import (
"encoding/json"
"fmt"
"os"
"sort"
"strings"
"unicode"
"unicode/utf8"
"github.com/ghodss/yaml"
"github.com/mitchellh/cli"
"github.com/mitchellh/go-wordwrap"
"github.com/ryanuber/columnize"
)
@@ -17,6 +21,39 @@ const (
hopeDelim = "♨"
)
// This is adapted from the code in the strings package for TrimSpace
var asciiSpace = [256]uint8{'\t': 1, '\n': 1, '\v': 1, '\f': 1, '\r': 1, ' ': 1}
func trimSpaceRight(in string) string {
for stop := len(in); stop > 0; stop-- {
c := in[stop-1]
if c >= utf8.RuneSelf {
return strings.TrimFunc(in[:stop], unicode.IsSpace)
}
if asciiSpace[c] == 0 {
return in[0:stop]
}
}
return ""
}
func WrapForHelpText(lines []string) string {
var ret []string
for _, line := range lines {
line = trimSpaceRight(line)
trimmed := strings.TrimSpace(line)
diff := uint(len(line) - len(trimmed))
wrapped := wordwrap.WrapString(trimmed, TermWidth-diff)
splitWrapped := strings.Split(wrapped, "\n")
for i := range splitWrapped {
splitWrapped[i] = fmt.Sprintf("%s%s", strings.Repeat(" ", int(diff)), strings.TrimSpace(splitWrapped[i]))
}
ret = append(ret, strings.Join(splitWrapped, "\n"))
}
return strings.Join(ret, "\n")
}
type FormatOptions struct {
Format string
}
@@ -25,7 +62,7 @@ type FormatOptions struct {
type JsonFormatter struct{}
func (j JsonFormatter) Format(data interface{}) ([]byte, error) {
return json.MarshalIndent(data, "", " ")
return json.Marshal(data)
}
/*
@@ -346,3 +383,29 @@ func looksLikeDuration(k string) bool {
k == "duration" || strings.HasSuffix(k, "_duration") ||
k == "lease_max" || k == "ttl_max"
}
type Formatter interface {
//Output(ui cli.Ui, secret *api.Secret, data interface{}) error
Format(data interface{}) ([]byte, error)
}
var Formatters = map[string]Formatter{
"json": JsonFormatter{},
"table": TableFormatter{},
"yaml": YamlFormatter{},
"yml": YamlFormatter{},
}
func Format(ui cli.Ui) string {
switch ui.(type) {
case *WatchtowerUI:
return ui.(*WatchtowerUI).Format
}
format := os.Getenv(EnvWatchtowerCLIFormat)
if format == "" {
format = "table"
}
return format
}
+71 -23
View File
@@ -27,6 +27,7 @@ import (
"github.com/hashicorp/watchtower/globals"
"github.com/hashicorp/watchtower/internal/db"
"github.com/hashicorp/watchtower/internal/iam"
"github.com/hashicorp/watchtower/internal/servers/controller/handlers/authenticate"
"github.com/hashicorp/watchtower/version"
"github.com/jinzhu/gorm"
"github.com/mitchellh/cli"
@@ -59,7 +60,8 @@ type Server struct {
Listeners []*ServerListener
DefaultOrgId string
DefaultOrgId string
DevAuthMethodId string
DevDatabaseUrl string
DevDatabaseCleanupFunc func() error
@@ -418,40 +420,86 @@ func (b *Server) CreateDevDatabase(dialect string) error {
cancel()
}()
var scope *iam.Scope
var orgScope *iam.Scope
if b.DefaultOrgId != "" {
scope, err = repo.LookupScope(ctx, b.DefaultOrgId)
orgScope, err = repo.LookupScope(ctx, b.DefaultOrgId)
if err != nil {
c()
return fmt.Errorf("error looking up existing scope with org ID %q: %w", b.DefaultOrgId, err)
}
if scope != nil {
goto INFO
}
}
scope, err = iam.NewOrg()
if err != nil {
c()
return fmt.Errorf("error creating new org scope: %w", err)
}
scope, err = repo.CreateScope(ctx, scope, iam.WithPublicId(b.DefaultOrgId))
if err != nil {
c()
return fmt.Errorf("error persisting new org scope: %w", err)
}
if b.DefaultOrgId != "" {
if scope.GetPublicId() != b.DefaultOrgId {
if orgScope == nil {
orgScope, err = iam.NewOrg()
if err != nil {
c()
return fmt.Errorf("expected org ID %q, got %q after persisting", b.DefaultOrgId, scope.GetPublicId())
return fmt.Errorf("error creating new org scope: %w", err)
}
orgScope, err = repo.CreateScope(ctx, orgScope, iam.WithPublicId(b.DefaultOrgId))
if err != nil {
c()
return fmt.Errorf("error persisting new org scope: %w", err)
}
if b.DefaultOrgId != "" {
if orgScope.GetPublicId() != b.DefaultOrgId {
c()
return fmt.Errorf("expected org ID %q, got %q after persisting", b.DefaultOrgId, orgScope.GetPublicId())
}
} else {
b.DefaultOrgId = orgScope.GetPublicId()
}
} else {
b.DefaultOrgId = scope.GetPublicId()
}
INFO:
b.InfoKeys = append(b.InfoKeys, "dev org id")
ar, err := iam.NewRole(orgScope.PublicId)
if err != nil {
return fmt.Errorf("error creating in memory role for anon authen: %w", err)
}
authenRole, err := repo.CreateRole(ctx, ar, iam.WithDescription("role for anon authen"))
if err != nil {
return fmt.Errorf("error creating role for anon authen: %w", err)
}
if _, err := repo.AddRoleGrants(ctx, authenRole.PublicId, authenRole.Version, []string{"type=auth-method;actions=list,authenticate"}); err != nil {
return fmt.Errorf("error creating grant for anon authen: %w", err)
}
if _, err := repo.AddPrincipalRoles(ctx, authenRole.PublicId, authenRole.Version+1, []string{"u_anon"}, nil); err != nil {
return fmt.Errorf("error adding principal to role for anon authen: %w", err)
}
pr, err := iam.NewRole(orgScope.PublicId)
if err != nil {
return fmt.Errorf("error creating in memory role for default dev grants: %w", err)
}
defPermsRole, err := repo.CreateRole(ctx, pr, iam.WithDescription("role for def grants"))
if err != nil {
return fmt.Errorf("error creating role for default dev grants: %w", err)
}
if _, err := repo.AddRoleGrants(ctx, defPermsRole.PublicId, defPermsRole.Version, []string{"id=*;actions=*"}); err != nil {
return fmt.Errorf("error creating grant for default dev grants: %w", err)
}
if _, err := repo.AddPrincipalRoles(ctx, defPermsRole.PublicId, defPermsRole.Version+1, []string{"u_auth"}, nil); err != nil {
return fmt.Errorf("error adding principal to role for default dev grants: %w", err)
}
// TODO: Remove this when Auth Account repo is in place.
authenticate.OrgScope = orgScope.GetPublicId()
insert := `insert into auth_method
(public_id, scope_id)
values
($1, $2);`
amId := b.DevAuthMethodId
if amId == "" {
amId = "am_1234567890"
}
authenticate.RWDb.Store(rw)
_, err = b.Database.DB().Exec(insert, amId, orgScope.GetPublicId())
if err != nil {
c()
return err
}
b.InfoKeys = append(b.InfoKeys, "dev org id", "dev auth method id")
b.Info["dev org id"] = b.DefaultOrgId
b.Info["dev auth method id"] = amId
return nil
}
+22
View File
@@ -0,0 +1,22 @@
package base
import (
"os"
"github.com/mitchellh/cli"
"golang.org/x/crypto/ssh/terminal"
)
type WatchtowerUI struct {
cli.Ui
Format string
}
var TermWidth uint = 80
func init() {
width, _, err := terminal.GetSize(int(os.Stdin.Fd()))
if err == nil {
TermWidth = uint(width)
}
}
+83
View File
@@ -6,10 +6,12 @@ import (
"syscall"
"github.com/hashicorp/watchtower/internal/cmd/base"
"github.com/hashicorp/watchtower/internal/cmd/commands/authenticate"
"github.com/hashicorp/watchtower/internal/cmd/commands/config"
"github.com/hashicorp/watchtower/internal/cmd/commands/controller"
"github.com/hashicorp/watchtower/internal/cmd/commands/dev"
"github.com/hashicorp/watchtower/internal/cmd/commands/hosts"
"github.com/hashicorp/watchtower/internal/cmd/commands/roles"
"github.com/hashicorp/watchtower/internal/cmd/commands/scopes"
"github.com/hashicorp/watchtower/internal/cmd/commands/worker"
@@ -82,6 +84,87 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
Command: base.NewCommand(ui),
}, nil
},
"authenticate": func() (cli.Command, error) {
return &authenticate.Command{
Command: base.NewCommand(ui),
}, nil
},
"authenticate password": func() (cli.Command, error) {
return &authenticate.PasswordCommand{
Command: base.NewCommand(ui),
}, nil
},
"roles": func() (cli.Command, error) {
return &roles.Command{
Command: base.NewCommand(ui),
}, nil
},
"roles create": func() (cli.Command, error) {
return &roles.Command{
Command: base.NewCommand(ui),
Func: "create",
}, nil
},
"roles update": func() (cli.Command, error) {
return &roles.Command{
Command: base.NewCommand(ui),
Func: "update",
}, nil
},
"roles read": func() (cli.Command, error) {
return &roles.Command{
Command: base.NewCommand(ui),
Func: "read",
}, nil
},
"roles delete": func() (cli.Command, error) {
return &roles.Command{
Command: base.NewCommand(ui),
Func: "delete",
}, nil
},
"roles list": func() (cli.Command, error) {
return &roles.Command{
Command: base.NewCommand(ui),
Func: "list",
}, nil
},
"roles add-principals": func() (cli.Command, error) {
return &roles.Command{
Command: base.NewCommand(ui),
Func: "add-principals",
}, nil
},
"roles set-principals": func() (cli.Command, error) {
return &roles.Command{
Command: base.NewCommand(ui),
Func: "set-principals",
}, nil
},
"roles remove-principals": func() (cli.Command, error) {
return &roles.Command{
Command: base.NewCommand(ui),
Func: "remove-principals",
}, nil
},
"roles add-grants": func() (cli.Command, error) {
return &roles.Command{
Command: base.NewCommand(ui),
Func: "add-grants",
}, nil
},
"roles set-grants": func() (cli.Command, error) {
return &roles.Command{
Command: base.NewCommand(ui),
Func: "set-grants",
}, nil
},
"roles remove-grants": func() (cli.Command, error) {
return &roles.Command{
Command: base.NewCommand(ui),
Func: "remove-grants",
}, nil
},
}
}
@@ -0,0 +1,35 @@
package authenticate
import (
"github.com/hashicorp/watchtower/internal/cmd/base"
"github.com/mitchellh/cli"
"github.com/mitchellh/go-wordwrap"
)
var _ cli.Command = (*Command)(nil)
type Command struct {
*base.Command
}
func (c *Command) Synopsis() string {
return wordwrap.WrapString("Authenticate the Watchtower commandline client", base.TermWidth)
}
func (c *Command) Help() string {
return base.WrapForHelpText([]string{
"Usage: watchtower authenticate [sub command] [options] [args]",
"",
" This command authenticates the Watchtower commandline client using a specified auth method. Examples:",
"",
" Authenticate with password auth method:",
"",
" $ watchtower authenticate password -name foo -password bar",
"",
" Please see the auth method subcommand help for detailed usage information.",
})
}
func (c *Command) Run(args []string) int {
return cli.RunResultHelp
}
@@ -0,0 +1,163 @@
package authenticate
import (
"fmt"
"os"
"strings"
"time"
"github.com/hashicorp/vault/sdk/helper/password"
"github.com/hashicorp/watchtower/api/scopes"
"github.com/hashicorp/watchtower/internal/cmd/base"
"github.com/kr/pretty"
"github.com/mitchellh/cli"
"github.com/mitchellh/go-wordwrap"
"github.com/posener/complete"
"github.com/zalando/go-keyring"
)
var _ cli.Command = (*PasswordCommand)(nil)
var _ cli.CommandAutocomplete = (*PasswordCommand)(nil)
var envPassword = "WATCHTOWER_AUTHENTICATE_PASSWORD"
var envName = "WATCHTOWER_AUTHENTICATE_NAME"
var envMethodId = "WATCHTOWER_AUTHENTICATE_METHOD_ID"
type PasswordCommand struct {
*base.Command
flagName string
flagPassword string
flagMethodId string
}
func (c *PasswordCommand) Synopsis() string {
return wordwrap.WrapString("Invoke the password auth method to authenticate with Watchtower", base.TermWidth)
}
func (c *PasswordCommand) Help() string {
return base.WrapForHelpText([]string{
"Usage: watchtower authenticate password [options] [args]",
"",
" Invoke the password auth method to authenticate the Watchtower CLI:",
"",
" $ watchtower authenticate password -name=foo -password=bar",
"",
" If more than one instance of the password auth method exists, use the -method-id flag:",
"",
` $ watchtower authenticate password -method-id am_12345 -name foo -password "bar"`,
}) + c.Flags().Help()
}
func (c *PasswordCommand) Flags() *base.FlagSets {
set := c.FlagSet(base.FlagSetHTTP | base.FlagSetClient | base.FlagSetOutputFormat)
f := set.NewFlagSet("Command Options")
f.StringVar(&base.StringVar{
Name: "name",
Target: &c.flagName,
EnvVar: envName,
Usage: "Login name",
})
f.StringVar(&base.StringVar{
Name: "password",
Target: &c.flagPassword,
EnvVar: envPassword,
Usage: "Password",
})
f.StringVar(&base.StringVar{
Name: "method-id",
Target: &c.flagMethodId,
EnvVar: envMethodId,
Usage: "Specify if more than one instance of a password auth method exists in the given org",
})
return set
}
func (c *PasswordCommand) AutocompleteArgs() complete.Predictor {
return complete.PredictAnything
}
func (c *PasswordCommand) AutocompleteFlags() complete.Flags {
return c.Flags().Completions()
}
func (c *PasswordCommand) Run(args []string) int {
f := c.Flags()
if err := f.Parse(args); err != nil {
c.UI.Error(err.Error())
return 1
}
switch {
case c.flagName == "":
c.UI.Error("Name must be provided via -name")
return 1
case c.flagMethodId == "":
c.UI.Error("Auth method ID must be provided via -method-id")
return 1
}
if c.flagPassword == "" {
fmt.Print("Password is not set as flag or in env, please enter it now (will be hidden): ")
value, err := password.Read(os.Stdin)
fmt.Print("\n")
if err != nil {
c.UI.Error(fmt.Sprintf("An error occurred attempting to read the password. The raw error message is shown below but usually this is because you attempted to pipe a value into the command or you are executing outside of a terminal (TTY). The raw error was:\n\n%s", err.Error()))
return 2
}
c.flagPassword = strings.TrimSpace(value)
}
client, err := c.Client()
if err != nil {
c.UI.Error(fmt.Sprintf("Error creating API client: %s", err.Error()))
return 2
}
org := &scopes.Org{
Client: client,
}
// note: Authenticate() calls SetToken() under the hood to set the
// auth bearer on the client so we do not need to do anything with the
// returned token after this call, so we ignore it
result, apiErr, err := org.Authenticate(c.Context, c.flagMethodId, c.flagName, c.flagPassword)
if err != nil {
c.UI.Error(fmt.Sprintf("Error trying to perform authentication: %s", err.Error()))
return 2
}
if apiErr != nil {
c.UI.Error(fmt.Sprintf("Error from controller when performing authentication: %s", pretty.Sprint(apiErr)))
return 1
}
switch base.Format(c.UI) {
case "table":
c.UI.Output(base.WrapForHelpText([]string{
"",
"Authentication information:",
fmt.Sprintf(" Token: %s", result.Token),
fmt.Sprintf(" User ID: %s", result.UserId),
fmt.Sprintf(" Expiration Time: %s", result.ExpirationTime.Local().Format(time.RFC3339)),
}))
}
tokenName := "default"
if c.Command.FlagTokenName != "" {
tokenName = c.Command.FlagTokenName
}
if tokenName != "none" {
if err := keyring.Set("HashiCorp Watchtower Auth Token", tokenName, result.Token); err != nil {
c.UI.Error(fmt.Sprintf("Error saving auth token to system credential store: %s", err))
return 1
}
}
return 0
}
@@ -48,6 +48,7 @@ type Command struct {
flagDevControllerAPIListenAddr string
flagDevControllerClusterListenAddr string
flagDevOrgId string
flagDevAuthMethodId string
flagDevPassthroughDirectory string
}
@@ -119,6 +120,14 @@ func (c *Command) Flags() *base.FlagSets {
"mode.",
})
f.StringVar(&base.StringVar{
Name: "dev-auth-method-id",
Target: &c.flagDevAuthMethodId,
EnvVar: "WATCHTWER_DEV_AUTH_METHOD_ID",
Usage: "Auto-created auth method ID. This only applies when running in \"dev\" " +
"mode.",
})
f.StringVar(&base.StringVar{
Name: "dev-admin-password",
Target: &c.flagDevAdminPassword,
@@ -336,6 +345,18 @@ func (c *Command) ParseFlagsAndConfig(args []string) int {
if c.flagDevOrgId != "" {
c.Config.DefaultOrgId = c.flagDevOrgId
}
if c.flagDevAuthMethodId != "" {
if !strings.HasPrefix(c.flagDevAuthMethodId, "am_") {
c.UI.Error(fmt.Sprintf("Invalid dev auth method ID, must start with %q", "am_"))
return 1
}
if len(c.flagDevAuthMethodId) != 13 {
c.UI.Error(fmt.Sprintf("Invalid dev auth method ID, must be 10 base62 characters after %q", "am_"))
return 1
}
c.DevAuthMethodId = c.flagDevAuthMethodId
}
c.Config.PassthroughDirectory = c.flagDevPassthroughDirectory
for _, l := range c.Config.Listeners {
+21
View File
@@ -36,6 +36,7 @@ type Command struct {
flagDev bool
flagDevAdminPassword string
flagDevOrgId string
flagDevAuthMethodId string
flagDevControllerAPIListenAddr string
flagDevControllerClusterListenAddr string
flagDevPassthroughDirectory string
@@ -92,6 +93,14 @@ func (c *Command) Flags() *base.FlagSets {
"mode.",
})
f.StringVar(&base.StringVar{
Name: "dev-auth-method-id",
Target: &c.flagDevAuthMethodId,
EnvVar: "WATCHTWER_DEV_AUTH_METHOD_ID",
Usage: "Auto-created auth method ID. This only applies when running in \"dev\" " +
"mode.",
})
f.StringVar(&base.StringVar{
Name: "dev-admin-password",
Target: &c.flagDevAdminPassword,
@@ -155,6 +164,18 @@ func (c *Command) Run(args []string) int {
if c.flagDevOrgId != "" {
devConfig.DefaultOrgId = c.flagDevOrgId
}
if c.flagDevAuthMethodId != "" {
if !strings.HasPrefix(c.flagDevAuthMethodId, "am_") {
c.UI.Error(fmt.Sprintf("Invalid dev auth method ID, must start with %q", "am_"))
return 1
}
if len(c.flagDevAuthMethodId) != 13 {
c.UI.Error(fmt.Sprintf("Invalid dev auth method ID, must be 10 base62 characters after %q", "am_"))
return 1
}
c.DevAuthMethodId = c.flagDevAuthMethodId
}
devConfig.PassthroughDirectory = c.flagDevPassthroughDirectory
for _, l := range devConfig.Listeners {
+1 -1
View File
@@ -45,7 +45,7 @@ Usage: watchtower hosts create
}
func (c *CreateCommand) Flags() *base.FlagSets {
set := c.FlagSet(base.FlagSetHTTP | base.FlagSetOutputFormat)
set := c.FlagSet(base.FlagSetHTTP | base.FlagSetClient | base.FlagSetOutputFormat)
f := set.NewFlagSet("Command Options")
+232
View File
@@ -0,0 +1,232 @@
package roles
import (
"fmt"
"net/textproto"
"strings"
"time"
"github.com/hashicorp/watchtower/api/roles"
"github.com/hashicorp/watchtower/internal/cmd/base"
"github.com/mitchellh/go-wordwrap"
)
func synopsisFunc(inFunc string) string {
if inFunc == "" {
return wordwrap.WrapString("Manage Watchtower roles", base.TermWidth)
}
return wordwrap.WrapString(fmt.Sprintf("%s a role within Watchtower", textproto.CanonicalMIMEHeaderKey(inFunc)), base.TermWidth)
}
func principalsGrantsSynopsisFunc(inFunc string, principals bool) string {
var in string
switchStr := "principals (users, groups)"
if !principals {
switchStr = "grants"
}
switch {
case strings.HasPrefix(inFunc, "add"):
in = fmt.Sprintf("Add %s to", switchStr)
case strings.HasPrefix(inFunc, "set"):
in = fmt.Sprintf("Set the full contents of the %s on", switchStr)
case strings.HasPrefix(inFunc, "remove"):
in = fmt.Sprintf("Remove %s from", switchStr)
}
return wordwrap.WrapString(fmt.Sprintf("%s a role within Watchtower", in), base.TermWidth)
}
func baseHelp() string {
return base.WrapForHelpText([]string{
"Usage: watchtower roles [sub command] [options] [args]",
"",
" This command allows operations on Watchtower roles. Examples:",
"",
" Create a role:",
"",
` $ watchtower roles create -name foo -description "For ProdOps usage"`,
"",
" Add a grant to a role:",
"",
` $ watchtower roles add-grants -id r_1234567890 -grant "type=host-catalog;actions=create,delete"`,
"",
" Please see the role subcommand help for detailed usage information.",
})
}
func createHelp() string {
return base.WrapForHelpText([]string{
"Usage: watchtower roles create [options] [args]",
"",
" Create a role. Example:",
"",
` $ watchtower roles create -name ops -description "Role for ops grants"`,
"",
"",
})
}
func updateHelp() string {
return base.WrapForHelpText([]string{
"Usage: watchtower roles update [options] [args]",
"",
" Update a role given its ID. Example:",
"",
` $ watchtower roles update -id r_1234567890 -description "Development host grants"`,
})
}
func readHelp() string {
return base.WrapForHelpText([]string{
"Usage: watchtower roles read [options] [args]",
"",
" Read a role given its ID. Example:",
"",
` $ watchtower roles read -id r_1234567890`,
})
}
func deleteHelp() string {
return base.WrapForHelpText([]string{
"Usage: watchtower roles delete [options] [args]",
"",
" Delete a role given its ID. Example:",
"",
` $ watchtower roles delete -id r_1234567890`,
})
}
func listHelp() string {
return base.WrapForHelpText([]string{
"Usage: watchtower roles list [options] [args]",
"",
" List roles within a scope. Example:",
"",
` $ watchtower roles list -org o_1234567890`,
})
}
func addPrincipalsHelp() string {
return base.WrapForHelpText([]string{
"Usage: watchtower roles add-principals [options] [args]",
"",
` Adds principals (users, groups) to a role given its ID. The "user" and "group" flags can be specified multiple times. Example:`,
"",
` $ watchtower roles add-principals -id r_1234567890 -user u_1234567890`,
})
}
func setPrincipalsHelp() string {
return base.WrapForHelpText([]string{
"Usage: watchtower roles set-principals [options] [args]",
"",
` Sets the complete set of principals (users, groups) on a role given its ID. The "user" and "group" flags can be specified multiple times. Example:`,
"",
` $ watchtower roles set-principals -id r_1234567890 -user u_anon -group sg_1234567890`,
})
}
func removePrincipalsHelp() string {
return base.WrapForHelpText([]string{
"Usage: watchtower roles remove-principals [options] [args]",
"",
` Removes principals (users, groups) from a role given its ID. The "user" and "group" flags can be specified multiple times. Example:`,
"",
` $ watchtower roles remove-principals -id r_1234567890 -group sg_1234567890`,
})
}
func populateFlags(c *Command, f *base.FlagSet, flagNames []string) {
for _, name := range flagNames {
switch name {
case "id":
f.StringVar(&base.StringVar{
Name: "id",
Target: &c.flagId,
Usage: "ID of the role to operate on",
})
case "name":
f.StringVar(&base.StringVar{
Name: "name",
Target: &c.flagName,
Usage: "Name to set on the role",
})
case "description":
f.StringVar(&base.StringVar{
Name: "description",
Target: &c.flagDescription,
Usage: "Description to set on the role",
})
case "grantscopeid":
f.StringVar(&base.StringVar{
Name: "grant-scope-id",
Target: &c.flagGrantScopeId,
Usage: "The scope ID for grants set on the role",
})
case "principal":
f.StringSliceVar(&base.StringSliceVar{
Name: "principal",
Target: &c.flagPrincipals,
Usage: "The principals (users or groups) to add, remove, or set. May be specified multiple times.",
})
case "grant":
f.StringSliceVar(&base.StringSliceVar{
Name: "grant",
Target: &c.flagGrants,
Usage: "The grants to add, remove, or set. May be specified multiple times. Can be in compact string format or JSON (be sure to escape JSON properly).",
})
}
}
}
func generateRoleTableOutput(role *roles.Role) string {
var output []string
if true {
output = []string{
"",
"Role information:",
fmt.Sprintf(" ID: %s", role.Id),
fmt.Sprintf(" Created At: %s", role.CreatedTime.Local().Format(time.RFC3339)),
fmt.Sprintf(" Updated At: %s", role.UpdatedTime.Local().Format(time.RFC3339)),
fmt.Sprintf(" Version: %d", role.Version),
}
}
if role.Name != nil {
output = append(output,
fmt.Sprintf(" Name: %s", *role.Name),
)
}
if role.Description != nil {
output = append(output,
fmt.Sprintf(" Description: %s", *role.Description),
)
}
if role.GrantScopeId != nil {
output = append(output,
fmt.Sprintf(" Grant Scope ID: %s", *role.GrantScopeId),
)
}
if len(role.Principals) > 0 {
output = append(output,
fmt.Sprintf(" Principals: %s", ""),
)
}
for _, principal := range role.Principals {
output = append(output,
fmt.Sprintf(" ID: %s", principal.Id),
fmt.Sprintf(" Type: %s", principal.Type),
fmt.Sprintf(" Scope ID: %s", principal.ScopeId),
)
}
if len(role.GrantsCanonical) > 0 {
output = append(output,
fmt.Sprintf(" Canonical Grants: %s", ""),
)
}
for _, grant := range role.GrantsCanonical {
output = append(output,
fmt.Sprintf(" %s", grant),
)
}
return base.WrapForHelpText(output)
}
+363
View File
@@ -0,0 +1,363 @@
package roles
import (
"context"
"fmt"
"github.com/hashicorp/vault/sdk/helper/strutil"
"github.com/hashicorp/watchtower/api"
"github.com/hashicorp/watchtower/api/roles"
"github.com/hashicorp/watchtower/api/scopes"
"github.com/hashicorp/watchtower/internal/cmd/base"
"github.com/hashicorp/watchtower/internal/perms"
"github.com/kr/pretty"
"github.com/mitchellh/cli"
"github.com/posener/complete"
)
var _ cli.Command = (*Command)(nil)
var _ cli.CommandAutocomplete = (*Command)(nil)
type Command struct {
*base.Command
Func string
flagId string
flagName string
flagDescription string
flagGrantScopeId string
flagPrincipals []string
flagGrants []string
}
func (c *Command) Synopsis() string {
switch c.Func {
case "create", "update", "read", "delete", "list":
return synopsisFunc(c.Func)
case "add-principals", "set-principals", "remove-principals":
return principalsGrantsSynopsisFunc(c.Func, true)
case "add-grants", "set-grants", "remove-grants":
return principalsGrantsSynopsisFunc(c.Func, false)
}
return "Manage Watchtower roles"
}
var helpMap = map[string]func() string{
"create": createHelp,
"update": updateHelp,
"read": readHelp,
"delete": deleteHelp,
"list": listHelp,
"add-principals": addPrincipalsHelp,
"set-principals": setPrincipalsHelp,
"remove-principals": removePrincipalsHelp,
"add-grants": addPrincipalsHelp,
"set-grants": setPrincipalsHelp,
"remove-grants": removePrincipalsHelp,
}
var flagsMap = map[string][]string{
"create": {"name", "description", "grantscopeid"},
"update": {"id", "name", "description", "grantscopeid"},
"read": {"id"},
"delete": {"id"},
"add-principals": {"id", "principal"},
"set-principals": {"id", "principal"},
"remove-principals": {"id", "principal"},
"add-grants": {"id", "grant"},
"set-grants": {"id", "grant"},
"remove-grants": {"id", "grant"},
}
func (c *Command) Help() string {
if c.Func == "" {
return baseHelp()
}
return helpMap[c.Func]() + "\n\n" + c.Flags().Help()
}
func (c *Command) Flags() *base.FlagSets {
set := c.FlagSet(base.FlagSetHTTP | base.FlagSetClient | base.FlagSetOutputFormat)
f := set.NewFlagSet("Command Options")
populateFlags(c, f, flagsMap[c.Func])
return set
}
func (c *Command) AutocompleteArgs() complete.Predictor {
return complete.PredictAnything
}
func (c *Command) AutocompleteFlags() complete.Flags {
return c.Flags().Completions()
}
func (c *Command) Run(args []string) int {
if c.Func == "" {
return cli.RunResultHelp
}
f := c.Flags()
if err := f.Parse(args); err != nil {
c.UI.Error(err.Error())
return 1
}
if strutil.StrListContains(flagsMap[c.Func], "id") && c.flagId == "" {
c.UI.Error("ID is required but not passed in via -id")
return 1
}
client, err := c.Client()
if err != nil {
c.UI.Error(fmt.Sprintf("Error creating API client: %s", err.Error()))
return 2
}
role := &roles.Role{
Client: client,
Id: c.flagId,
}
switch c.flagName {
case "":
case "null":
role.SetDefault("name")
default:
role.Name = api.String(c.flagName)
}
switch c.flagDescription {
case "":
case "null":
role.SetDefault("description")
default:
role.Description = api.String(c.flagDescription)
}
switch c.flagGrantScopeId {
case "":
case "null":
role.SetDefault("grantscopeid")
default:
role.GrantScopeId = api.String(c.flagGrantScopeId)
}
principals := c.flagPrincipals
grants := c.flagGrants
switch c.Func {
case "add-principals", "remove-principals":
if len(c.flagPrincipals) == 0 {
c.UI.Error("No principals supplied via -principal")
return 1
}
case "add-grants", "remove-grants":
if len(c.flagGrants) == 0 {
c.UI.Error("No grants supplied via -grant")
return 1
}
case "set-principals":
switch len(c.flagPrincipals) {
case 0:
case 1:
if c.flagPrincipals[0] == "null" {
principals = []string{}
}
}
if principals == nil {
c.UI.Error("No principals supplied via -principals")
return 1
}
case "set-grants":
switch len(c.flagGrants) {
case 0:
case 1:
if c.flagGrants[0] == "null" {
grants = []string{}
}
}
if grants == nil {
c.UI.Error("No grants supplied via -grant")
return 1
}
}
if len(grants) > 0 {
for _, grant := range grants {
_, err := perms.Parse("global", "", grant)
if err != nil {
c.UI.Error(fmt.Errorf("Grant %q could not be parsed successfully: %w", grant, err).Error())
return 1
}
}
}
var apiErr *api.Error
type crudl interface {
CreateRole(context.Context, *roles.Role) (*roles.Role, *api.Error, error)
UpdateRole(context.Context, *roles.Role) (*roles.Role, *api.Error, error)
ReadRole(context.Context, *roles.Role) (*roles.Role, *api.Error, error)
DeleteRole(context.Context, *roles.Role) (bool, *api.Error, error)
ListRoles(context.Context) ([]*roles.Role, *api.Error, error)
}
var actor crudl
var existed bool
var listedRoles []*roles.Role
switch {
case client.Project() != "":
project := &scopes.Project{
Client: client,
}
actor = project
case client.Org() != "":
org := &scopes.Org{
Client: client,
}
actor = org
default:
// TODO: Handle global case
c.UI.Error("TODO")
}
if actor == nil {
c.UI.Error("Unable to determine the right scope for the command")
return 1
}
// Perform check-and-set when needed
switch c.Func {
case "create", "read", "delete", "list":
// These don't udpate so don't need the existing version
default:
existingRole, existingApiErr, existingErr := actor.ReadRole(c.Context, role)
if existingErr != nil {
c.UI.Error(fmt.Sprintf("Error performing initial check-and-set read: %s", err.Error()))
return 2
}
if existingApiErr != nil {
c.UI.Error(fmt.Sprintf("Error from controller when performing initial check-and-set read: %s", pretty.Sprint(apiErr)))
return 1
}
role.Version = existingRole.Version
}
switch c.Func {
case "create":
role, apiErr, err = actor.CreateRole(c.Context, role)
case "update":
role, apiErr, err = actor.UpdateRole(c.Context, role)
case "read":
role, apiErr, err = actor.ReadRole(c.Context, role)
case "delete":
existed, apiErr, err = actor.DeleteRole(c.Context, role)
case "list":
listedRoles, apiErr, err = actor.ListRoles(c.Context)
case "add-principals":
role, apiErr, err = role.AddPrincipals(c.Context, principals)
case "set-principals":
role, apiErr, err = role.SetPrincipals(c.Context, principals)
case "remove-principals":
role, apiErr, err = role.RemovePrincipals(c.Context, principals)
case "add-grants":
role, apiErr, err = role.AddGrants(c.Context, grants)
case "set-grants":
role, apiErr, err = role.SetGrants(c.Context, grants)
case "remove-grants":
role, apiErr, err = role.RemoveGrants(c.Context, grants)
}
plural := "role"
if c.Func == "list" {
plural = "roles"
}
if err != nil {
c.UI.Error(fmt.Sprintf("Error trying to %s %s: %s", c.Func, plural, err.Error()))
return 2
}
if apiErr != nil {
c.UI.Error(fmt.Sprintf("Error from controller when performing %s on %s: %s", c.Func, plural, pretty.Sprint(apiErr)))
return 1
}
switch c.Func {
case "delete":
switch base.Format(c.UI) {
case "json":
c.UI.Output("null")
case "table":
output := "The delete operation completed successfully"
switch existed {
case true:
output += "."
default:
output += ", however the resource did not exist at the time."
}
c.UI.Output(output)
}
return 0
case "list":
if len(listedRoles) == 0 {
c.UI.Output("No roles found")
return 0
}
switch base.Format(c.UI) {
case "json":
b, err := base.JsonFormatter{}.Format(listedRoles)
if err != nil {
c.UI.Error(fmt.Errorf("Error formatting to JSON: %w", err).Error())
return 1
}
c.UI.Output(string(b))
case "table":
var output []string
output = []string{
"",
"Role information:",
}
for i, r := range listedRoles {
if i > 0 {
output = append(output, "")
}
if true {
output = append(output,
fmt.Sprintf(" ID: %s", r.Id),
)
}
if r.Name != nil {
output = append(output,
fmt.Sprintf(" Name: %s", *r.Name),
)
}
if r.Description != nil {
output = append(output,
fmt.Sprintf(" Description: %s", *r.Description),
)
}
}
c.UI.Output(base.WrapForHelpText(output))
}
return 0
}
switch base.Format(c.UI) {
case "table":
c.UI.Output(generateRoleTableOutput(role))
case "json":
b, err := base.JsonFormatter{}.Format(role)
if err != nil {
c.UI.Error(fmt.Errorf("Error formatting to JSON: %w", err).Error())
return 1
}
c.UI.Output(string(b))
}
return 0
}
+36
View File
@@ -0,0 +1,36 @@
package scopes
import (
"fmt"
"time"
"github.com/hashicorp/watchtower/api/scopes"
"github.com/hashicorp/watchtower/internal/cmd/base"
)
func printProject(in *scopes.Project) string {
var ret []string
// This if true is here to line up columns for easy editing
if true {
ret = append(ret, []string{
"",
"Project information:",
fmt.Sprintf(" ID: %s", in.Id),
fmt.Sprintf(" Created Time: %s", in.CreatedTime.Local().Format(time.RFC3339)),
fmt.Sprintf(" Updated Time: %s", in.UpdatedTime.Local().Format(time.RFC3339)),
}...,
)
}
if in.Name != nil {
ret = append(ret,
fmt.Sprintf(" Name: %s", *in.Name),
)
}
if in.Description != nil {
ret = append(ret,
fmt.Sprintf(" Description: %s", *in.Description),
)
}
return base.WrapForHelpText(ret)
}
@@ -43,7 +43,7 @@ Usage: watchtower projects create
}
func (c *CreateProjectCommand) Flags() *base.FlagSets {
set := c.FlagSet(base.FlagSetHTTP | base.FlagSetOutputFormat)
set := c.FlagSet(base.FlagSetHTTP | base.FlagSetClient | base.FlagSetOutputFormat)
f := set.NewFlagSet("Command Options")
@@ -105,8 +105,11 @@ func (c *CreateProjectCommand) Run(args []string) int {
case apiErr != nil:
c.UI.Error(pretty.Sprint(apiErr))
return 2
default:
c.UI.Info(pretty.Sprint(project))
}
switch base.Format(c.UI) {
case "table":
c.UI.Output(printProject(project))
}
return 0
+6 -3
View File
@@ -43,7 +43,7 @@ Usage: watchtower projects read
}
func (c *ReadProjectCommand) Flags() *base.FlagSets {
set := c.FlagSet(base.FlagSetHTTP | base.FlagSetOutputFormat)
set := c.FlagSet(base.FlagSetHTTP | base.FlagSetClient | base.FlagSetOutputFormat)
f := set.NewFlagSet("Command Options")
@@ -97,8 +97,11 @@ func (c *ReadProjectCommand) Run(args []string) int {
case apiErr != nil:
c.UI.Error(pretty.Sprint(apiErr))
return 2
default:
c.UI.Info(pretty.Sprint(project))
}
switch base.Format(c.UI) {
case "table":
c.UI.Output(printProject(project))
}
return 0
-34
View File
@@ -1,34 +0,0 @@
package cmd
import (
"os"
"github.com/hashicorp/watchtower/internal/cmd/base"
"github.com/mitchellh/cli"
)
type Formatter interface {
//Output(ui cli.Ui, secret *api.Secret, data interface{}) error
Format(data interface{}) ([]byte, error)
}
var Formatters = map[string]Formatter{
"json": base.JsonFormatter{},
"table": base.TableFormatter{},
"yaml": base.YamlFormatter{},
"yml": base.YamlFormatter{},
}
func Format(ui cli.Ui) string {
switch ui.(type) {
case *WatchtowerUI:
return ui.(*WatchtowerUI).format
}
format := os.Getenv(base.EnvWatchtowerCLIFormat)
if format == "" {
format = "table"
}
return format
}
+5 -10
View File
@@ -18,11 +18,6 @@ import (
"github.com/mitchellh/cli"
)
type WatchtowerUI struct {
cli.Ui
format string
}
// setupEnv parses args and may replace them and sets some env vars to known
// values based on format options
func setupEnv(args []string) (retArgs []string, format string, outputCurlString bool) {
@@ -128,7 +123,7 @@ func RunCustom(args []string, runOpts *RunOptions) int {
uiErrWriter = ioutil.Discard
}
ui := &WatchtowerUI{
ui := &base.WatchtowerUI{
Ui: &cli.ColoredUi{
ErrorColor: cli.UiColorRed,
WarnColor: cli.UiColorYellow,
@@ -138,10 +133,10 @@ func RunCustom(args []string, runOpts *RunOptions) int {
ErrorWriter: uiErrWriter,
},
},
format: format,
Format: format,
}
serverCmdUi := &WatchtowerUI{
serverCmdUi := &base.WatchtowerUI{
Ui: &cli.ColoredUi{
ErrorColor: cli.UiColorRed,
WarnColor: cli.UiColorYellow,
@@ -150,10 +145,10 @@ func RunCustom(args []string, runOpts *RunOptions) int {
Writer: runOpts.Stdout,
},
},
format: format,
Format: format,
}
if _, ok := Formatters[format]; !ok {
if _, ok := base.Formatters[format]; !ok {
ui.Error(fmt.Sprintf("Invalid output format: %s", format))
return 1
}
+67 -11
View File
@@ -11,7 +11,7 @@ import (
"github.com/stretchr/testify/require"
)
func TestDomain_PublicPrivateId(t *testing.T) {
func TestDomain_Ids(t *testing.T) {
const (
createTableBase = `
create table if not exists test_table_{{rep}}_id (
@@ -29,7 +29,7 @@ returning id;
conn, _ := TestSetup(t, "postgres")
db := conn.DB()
for _, typ := range []string{"public", "private"} {
for _, typ := range []string{"public", "private", "role", "scope"} {
createTable := strings.Replace(createTableBase, "{{rep}}", typ, -1)
insert := strings.Replace(insertBase, "{{rep}}", typ, -1)
@@ -37,17 +37,44 @@ returning id;
t.Fatalf("query: \n%s\n error: %s", createTable, err)
}
failTests := []string{
" ",
"bar",
"00000009",
failTests := []struct {
value string
exception string
}{
{
" ",
"",
},
{
"bar",
"",
},
{
"00000009",
"",
},
{
"r_default",
"role",
},
{
"global",
"scope",
},
}
for _, tt := range failTests {
value := tt
t.Run(tt, func(t *testing.T) {
t.Logf("insert value: %q", value)
if _, err := db.Query(insert, value); err == nil {
t.Errorf("want error, got no error for inserting public_id: %s", value)
t.Run(tt.value, func(t *testing.T) {
t.Logf("insert value: %q", tt.value)
_, err := db.Query(insert, tt.value)
switch {
case err == nil && tt.exception != typ:
t.Errorf("want error, got no error for inserting public_id: %s", tt.value)
case err == nil && tt.exception == typ:
// All good
case err != nil && tt.exception != typ:
// All good
default:
t.Fatal("unhandled")
}
})
}
@@ -345,3 +372,32 @@ returning public_id;
require.NoError(err)
assert.Equal(3, v)
}
func TestDomain_DisallowDefaultRoleModification(t *testing.T) {
conn, _ := TestSetup(t, "postgres")
db := conn.DB()
_, err := db.Exec(`delete from iam_role where public_id = $1`, "r_default")
require.Error(t, err)
assert.Equal(t, `pq: deletion of default role not allowed`, err.Error())
// This actually tests not just default, but all roles
_, err = db.Exec(`update iam_role set public_id = $1 where public_id = $2`, "r_something", "r_default")
require.Error(t, err)
assert.Equal(t, `pq: update of role primary key not allowed`, err.Error())
}
func TestDomain_DefaultUsersExist(t *testing.T) {
conn, _ := TestSetup(t, "postgres")
db := conn.DB()
for _, val := range []string{"u_anon", "u_auth"} {
rows, err := db.Query(`select from iam_user where public_id = $1`, val)
require.NoError(t, err)
var count int
for rows.Next() {
count++
}
assert.Equal(t, 1, count)
}
}
+72 -13
View File
@@ -59,6 +59,13 @@ check(
comment on domain wt_scope_id is
'"u_anon", "u_auth", or random ID generated with github.com/hashicorp/vault/sdk/helper/base62';
create domain wt_role_id as text
check(
length(trim(value)) > 10 or value = 'r_default'
);
comment on domain wt_scope_id is
'"r_default", or random ID generated with github.com/hashicorp/vault/sdk/helper/base62';
create domain wt_timestamp as
timestamp with time zone
default current_timestamp;
@@ -453,7 +460,7 @@ drop table iam_role_grant cascade;
drop function iam_sub_names cascade;
drop function iam_immutable_scope_type_func cascade;
drop function iam_sub_scopes_func cascade;
drop function iam_immutable_role cascade;
drop function iam_immutable_role_principal cascade;
drop function iam_user_role_scope_check cascade;
drop function iam_group_role_scope_check cascade;
drop function iam_group_member_scope_check cascade;
@@ -814,7 +821,7 @@ insert into iam_user (public_id, name, description, scope_id)
values ('u_auth', 'authenticated', 'The authenticated user matches any user that has a valid token', 'global');
create table iam_role (
public_id wt_public_id primary key,
public_id wt_role_id primary key,
create_time wt_timestamp,
update_time wt_timestamp,
name text,
@@ -837,7 +844,7 @@ create table iam_role (
-- Grants are immutable, which is enforced via the trigger below
create table iam_role_grant (
create_time wt_timestamp,
role_id wt_public_id -- pk
role_id wt_role_id -- pk
references iam_role(public_id)
on delete cascade
on update cascade,
@@ -907,6 +914,51 @@ before
insert or update on iam_role
for each row execute procedure grant_scope_id_valid();
-- disallow_default_role_deletion prevents the default role (r_default) from
-- being deleted
create or replace function
disallow_default_role_deletion()
returns trigger
as $$
begin
if old.public_id = 'r_default' then
raise exception 'deletion of default role not allowed';
end if;
return old;
end;
$$ language plpgsql;
create trigger
disallow_default_role_deletion
before
delete on iam_role
for each row execute procedure disallow_default_role_deletion();
-- immutable_default_role_id prevents the a role's id from being updated.
create or replace function
immutable_role_id()
returns trigger
as $$
begin
if new.public_id is distinct from old.public_id then
raise exception 'update of role primary key not allowed';
end if;
return new;
end;
$$ language plpgsql;
create trigger
immutable_role_id
before
update on iam_role
for each row execute procedure immutable_role_id();
insert into iam_role (public_id, name, description, scope_id)
values('r_default', 'default', 'default role', 'global');
insert into iam_role_grant (role_id, canonical_grant, raw_grant)
values('r_default', 'type=org;actions=list', 'type=org;actions=list');
create table iam_group (
public_id wt_public_id not null primary key,
create_time wt_timestamp,
@@ -953,10 +1005,11 @@ update on iam_group
-- iam_user_role contains roles that have been assigned to users. Users can be
-- from any scope. The rows in this table must be immutable after insert, which
-- will be ensured with a before update trigger using iam_immutable_role().
-- will be ensured with a before update trigger using
-- iam_immutable_role_principal().
create table iam_user_role (
create_time wt_timestamp,
role_id wt_public_id
role_id wt_role_id
references iam_role(public_id)
on delete cascade
on update cascade,
@@ -970,10 +1023,10 @@ create table iam_user_role (
-- iam_group_role contains roles that have been assigned to groups.
-- Groups can be from any scope. The rows in this table must be immutable after
-- insert, which will be ensured with a before update trigger using
-- iam_immutable_role().
-- iam_immutable_role_principal().
create table iam_group_role (
create_time wt_timestamp,
role_id wt_public_id
role_id wt_role_id
references iam_role(public_id)
on delete cascade
on update cascade,
@@ -997,6 +1050,12 @@ begin
end;
$$ language plpgsql;
insert into iam_user_role (role_id, principal_id)
values
('r_default', 'u_anon'),
('r_default', 'u_auth');
-- iam_principle_role provides a consolidated view all principal roles assigned
-- (user and group roles).
create view iam_principal_role as
@@ -1032,9 +1091,9 @@ where
gr.role_id = r.public_id and
g.public_id = gr.principal_id;
-- iam_immutable_role() ensures that roles assigned to principals are immutable.
-- iam_immutable_role_principal() ensures that roles assigned to principals are immutable.
create or replace function
iam_immutable_role()
iam_immutable_role_principal()
returns trigger
as $$
begin
@@ -1042,10 +1101,10 @@ begin
end;
$$ language plpgsql;
create trigger immutable_role
create trigger immutable_role_principal
before
update on iam_user_role
for each row execute procedure iam_immutable_role();
for each row execute procedure iam_immutable_role_principal();
create trigger
immutable_create_time
@@ -1059,10 +1118,10 @@ before
insert on iam_user_role
for each row execute procedure default_create_time();
create trigger immutable_role
create trigger immutable_role_principal
before
update on iam_group_role
for each row execute procedure iam_immutable_role();
for each row execute procedure iam_immutable_role_principal();
create trigger
immutable_create_time
@@ -28,6 +28,13 @@ check(
comment on domain wt_scope_id is
'"u_anon", "u_auth", or random ID generated with github.com/hashicorp/vault/sdk/helper/base62';
create domain wt_role_id as text
check(
length(trim(value)) > 10 or value = 'r_default'
);
comment on domain wt_scope_id is
'"r_default", or random ID generated with github.com/hashicorp/vault/sdk/helper/base62';
create domain wt_timestamp as
timestamp with time zone
default current_timestamp;
@@ -18,7 +18,7 @@ drop table iam_role_grant cascade;
drop function iam_sub_names cascade;
drop function iam_immutable_scope_type_func cascade;
drop function iam_sub_scopes_func cascade;
drop function iam_immutable_role cascade;
drop function iam_immutable_role_principal cascade;
drop function iam_user_role_scope_check cascade;
drop function iam_group_role_scope_check cascade;
drop function iam_group_member_scope_check cascade;
+64 -12
View File
@@ -339,7 +339,7 @@ insert into iam_user (public_id, name, description, scope_id)
values ('u_auth', 'authenticated', 'The authenticated user matches any user that has a valid token', 'global');
create table iam_role (
public_id wt_public_id primary key,
public_id wt_role_id primary key,
create_time wt_timestamp,
update_time wt_timestamp,
name text,
@@ -362,7 +362,7 @@ create table iam_role (
-- Grants are immutable, which is enforced via the trigger below
create table iam_role_grant (
create_time wt_timestamp,
role_id wt_public_id -- pk
role_id wt_role_id -- pk
references iam_role(public_id)
on delete cascade
on update cascade,
@@ -432,6 +432,51 @@ before
insert or update on iam_role
for each row execute procedure grant_scope_id_valid();
-- disallow_default_role_deletion prevents the default role (r_default) from
-- being deleted
create or replace function
disallow_default_role_deletion()
returns trigger
as $$
begin
if old.public_id = 'r_default' then
raise exception 'deletion of default role not allowed';
end if;
return old;
end;
$$ language plpgsql;
create trigger
disallow_default_role_deletion
before
delete on iam_role
for each row execute procedure disallow_default_role_deletion();
-- immutable_default_role_id prevents the a role's id from being updated.
create or replace function
immutable_role_id()
returns trigger
as $$
begin
if new.public_id is distinct from old.public_id then
raise exception 'update of role primary key not allowed';
end if;
return new;
end;
$$ language plpgsql;
create trigger
immutable_role_id
before
update on iam_role
for each row execute procedure immutable_role_id();
insert into iam_role (public_id, name, description, scope_id)
values('r_default', 'default', 'default role', 'global');
insert into iam_role_grant (role_id, canonical_grant, raw_grant)
values('r_default', 'type=org;actions=list', 'type=org;actions=list');
create table iam_group (
public_id wt_public_id not null primary key,
create_time wt_timestamp,
@@ -478,10 +523,11 @@ update on iam_group
-- iam_user_role contains roles that have been assigned to users. Users can be
-- from any scope. The rows in this table must be immutable after insert, which
-- will be ensured with a before update trigger using iam_immutable_role().
-- will be ensured with a before update trigger using
-- iam_immutable_role_principal().
create table iam_user_role (
create_time wt_timestamp,
role_id wt_public_id
role_id wt_role_id
references iam_role(public_id)
on delete cascade
on update cascade,
@@ -495,10 +541,10 @@ create table iam_user_role (
-- iam_group_role contains roles that have been assigned to groups.
-- Groups can be from any scope. The rows in this table must be immutable after
-- insert, which will be ensured with a before update trigger using
-- iam_immutable_role().
-- iam_immutable_role_principal().
create table iam_group_role (
create_time wt_timestamp,
role_id wt_public_id
role_id wt_role_id
references iam_role(public_id)
on delete cascade
on update cascade,
@@ -522,6 +568,12 @@ begin
end;
$$ language plpgsql;
insert into iam_user_role (role_id, principal_id)
values
('r_default', 'u_anon'),
('r_default', 'u_auth');
-- iam_principle_role provides a consolidated view all principal roles assigned
-- (user and group roles).
create view iam_principal_role as
@@ -557,9 +609,9 @@ where
gr.role_id = r.public_id and
g.public_id = gr.principal_id;
-- iam_immutable_role() ensures that roles assigned to principals are immutable.
-- iam_immutable_role_principal() ensures that roles assigned to principals are immutable.
create or replace function
iam_immutable_role()
iam_immutable_role_principal()
returns trigger
as $$
begin
@@ -567,10 +619,10 @@ begin
end;
$$ language plpgsql;
create trigger immutable_role
create trigger immutable_role_principal
before
update on iam_user_role
for each row execute procedure iam_immutable_role();
for each row execute procedure iam_immutable_role_principal();
create trigger
immutable_create_time
@@ -584,10 +636,10 @@ before
insert on iam_user_role
for each row execute procedure default_create_time();
create trigger immutable_role
create trigger immutable_role_principal
before
update on iam_group_role
for each row execute procedure iam_immutable_role();
for each row execute procedure iam_immutable_role_principal();
create trigger
immutable_create_time
+74 -75
View File
@@ -72,6 +72,46 @@
]
}
},
"/v1/orgs/{org_id}/auth-methods/{auth_method_id}:authenticate": {
"post": {
"summary": "Authenticate a user to an Org and retrieve an authentication token.",
"operationId": "AuthenticationService_Authenticate",
"responses": {
"200": {
"description": "",
"schema": {
"$ref": "#/definitions/controller.api.resources.authtokens.v1.AuthToken"
}
}
},
"parameters": [
{
"name": "org_id",
"in": "path",
"required": true,
"type": "string"
},
{
"name": "auth_method_id",
"description": "The id to the authmethod in the system being used for authentication. The auth method must be in the org\nbeing logged in to.",
"in": "path",
"required": true,
"type": "string"
},
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/controller.api.services.v1.AuthenticateRequest"
}
}
],
"tags": [
"controller.api.services.v1.AuthenticationService"
]
}
},
"/v1/orgs/{org_id}/groups": {
"get": {
"summary": "Lists all Groups",
@@ -3051,43 +3091,10 @@
]
}
},
"/v1/orgs/{org_id}:authenticate": {
"post": {
"summary": "Authenticate a user to an Org and retrieve an authentication token.",
"operationId": "OrgService_Authenticate",
"responses": {
"200": {
"description": "",
"schema": {
"$ref": "#/definitions/controller.api.resources.authtokens.v1.AuthToken"
}
}
},
"parameters": [
{
"name": "org_id",
"in": "path",
"required": true,
"type": "string"
},
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/controller.api.services.v1.AuthenticateRequest"
}
}
],
"tags": [
"controller.api.services.v1.OrgService"
]
}
},
"/v1/orgs/{org_id}:deauthenticate": {
"post": {
"summary": "Deauthenticate an authentication token from an Org.",
"operationId": "OrgService_Deauthenticate",
"operationId": "AuthenticationService_Deauthenticate",
"responses": {
"200": {
"description": "A successful response.",
@@ -3105,7 +3112,7 @@
}
],
"tags": [
"controller.api.services.v1.OrgService"
"controller.api.services.v1.AuthenticationService"
]
}
}
@@ -3339,6 +3346,26 @@
},
"title": "HostSet is a collection of Hosts created and managed by a HostCatalog"
},
"controller.api.resources.roles.v1.Principal": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "The ID of the principal.\nOutput only.",
"readOnly": true
},
"type": {
"type": "string",
"description": "The type of the principal.\nOutput only.",
"readOnly": true
},
"scope_id": {
"type": "string",
"description": "The scope ID of the principal.\nOutput only.",
"readOnly": true
}
}
},
"controller.api.resources.roles.v1.Role": {
"type": "object",
"properties": {
@@ -3382,20 +3409,20 @@
"description": "The version can be used in subsiquent write requests to ensure this resource\nhas not changed and to fail the write if it has.\nOutput only.",
"readOnly": true
},
"user_ids": {
"principal_ids": {
"type": "array",
"items": {
"type": "string"
},
"description": "The principals that are assigned this role.\nOutput only.",
"description": "The IDs (only) of principals that are assigned to this role.\nOutput only.",
"readOnly": true
},
"group_ids": {
"principals": {
"type": "array",
"items": {
"type": "string"
"$ref": "#/definitions/controller.api.resources.roles.v1.Principal"
},
"description": "Output only.",
"description": "The principals that are assigned to this role.\nOutput only.",
"readOnly": true
},
"grants": {
@@ -3403,7 +3430,7 @@
"items": {
"type": "string"
},
"description": "The grants that this role provides for it's principals.\nOutput only.",
"description": "The grants that this role provides for its principals.\nOutput only.",
"readOnly": true
},
"grants_canonical": {
@@ -3578,13 +3605,7 @@
"format": "int64",
"description": "The version ensures the role hasn't changed since it was last retrieved and if\nit has the request will fail."
},
"user_ids": {
"type": "array",
"items": {
"type": "string"
}
},
"group_ids": {
"principal_ids": {
"type": "array",
"items": {
"type": "string"
@@ -3617,8 +3638,9 @@
"type": "string",
"description": "This can be \"cookie\" or \"token\". If not provided, \"token\" will be used. For now only type \"token\" is returned."
},
"password_credential": {
"$ref": "#/definitions/controller.api.services.v1.PasswordCredential"
"credentials": {
"type": "object",
"description": "credentials are the different possible credential names depending on what type of auth method is used.\nFor password auth method: should include only \"name\" and \"password\"."
}
}
},
@@ -3925,17 +3947,6 @@
}
}
},
"controller.api.services.v1.PasswordCredential": {
"type": "object",
"properties": {
"login_name": {
"type": "string"
},
"password": {
"type": "string"
}
}
},
"controller.api.services.v1.RemoveFromHostSetResponse": {
"type": "object"
},
@@ -3989,13 +4000,7 @@
"format": "int64",
"description": "The version ensures the role hasn't changed since it was last retrieved and if\nit has the request will fail."
},
"user_ids": {
"type": "array",
"items": {
"type": "string"
}
},
"group_ids": {
"principal_ids": {
"type": "array",
"items": {
"type": "string"
@@ -4061,13 +4066,7 @@
"format": "int64",
"description": "The version ensures the role hasn't changed since it was last retrieved and if\nit has the request will fail."
},
"user_ids": {
"type": "array",
"items": {
"type": "string"
}
},
"group_ids": {
"principal_ids": {
"type": "array",
"items": {
"type": "string"
@@ -27,6 +27,113 @@ const (
// of the legacy proto package is being used.
const _ = proto.ProtoPackageIsVersion4
type Principal struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// The ID of the principal.
// Output only.
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
// The type of the principal.
// Output only.
Type string `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"`
// The scope ID of the principal.
// Output only.
ScopeId string `protobuf:"bytes,3,opt,name=scope_id,proto3" json:"scope_id,omitempty"`
}
func (x *Principal) Reset() {
*x = Principal{}
if protoimpl.UnsafeEnabled {
mi := &file_controller_api_resources_roles_v1_role_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Principal) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Principal) ProtoMessage() {}
func (x *Principal) ProtoReflect() protoreflect.Message {
mi := &file_controller_api_resources_roles_v1_role_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Principal.ProtoReflect.Descriptor instead.
func (*Principal) Descriptor() ([]byte, []int) {
return file_controller_api_resources_roles_v1_role_proto_rawDescGZIP(), []int{0}
}
func (x *Principal) GetId() string {
if x != nil {
return x.Id
}
return ""
}
func (x *Principal) GetType() string {
if x != nil {
return x.Type
}
return ""
}
func (x *Principal) GetScopeId() string {
if x != nil {
return x.ScopeId
}
return ""
}
type Grant struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *Grant) Reset() {
*x = Grant{}
if protoimpl.UnsafeEnabled {
mi := &file_controller_api_resources_roles_v1_role_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Grant) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Grant) ProtoMessage() {}
func (x *Grant) ProtoReflect() protoreflect.Message {
mi := &file_controller_api_resources_roles_v1_role_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Grant.ProtoReflect.Descriptor instead.
func (*Grant) Descriptor() ([]byte, []int) {
return file_controller_api_resources_roles_v1_role_proto_rawDescGZIP(), []int{1}
}
// Role contains all fields related to a Role resource
type Role struct {
state protoimpl.MessageState
@@ -58,12 +165,13 @@ type Role struct {
// has not changed and to fail the write if it has.
// Output only.
Version uint32 `protobuf:"varint,8,opt,name=version,proto3" json:"version,omitempty"`
// The principals that are assigned this role.
// The IDs (only) of principals that are assigned to this role.
// Output only.
UserIds []string `protobuf:"bytes,9,rep,name=user_ids,json=userIds,proto3" json:"user_ids,omitempty"`
PrincipalIds []string `protobuf:"bytes,9,rep,name=principal_ids,proto3" json:"principal_ids,omitempty"`
// The principals that are assigned to this role.
// Output only.
GroupIds []string `protobuf:"bytes,10,rep,name=group_ids,json=groupIds,proto3" json:"group_ids,omitempty"`
// The grants that this role provides for it's principals.
Principals []*Principal `protobuf:"bytes,10,rep,name=principals,proto3" json:"principals,omitempty"`
// The grants that this role provides for its principals.
// Output only.
Grants []string `protobuf:"bytes,11,rep,name=grants,proto3" json:"grants,omitempty"`
// The canonical version of the grants in the grants field with the same index.
@@ -77,7 +185,7 @@ type Role struct {
func (x *Role) Reset() {
*x = Role{}
if protoimpl.UnsafeEnabled {
mi := &file_controller_api_resources_roles_v1_role_proto_msgTypes[0]
mi := &file_controller_api_resources_roles_v1_role_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -90,7 +198,7 @@ func (x *Role) String() string {
func (*Role) ProtoMessage() {}
func (x *Role) ProtoReflect() protoreflect.Message {
mi := &file_controller_api_resources_roles_v1_role_proto_msgTypes[0]
mi := &file_controller_api_resources_roles_v1_role_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -103,7 +211,7 @@ func (x *Role) ProtoReflect() protoreflect.Message {
// Deprecated: Use Role.ProtoReflect.Descriptor instead.
func (*Role) Descriptor() ([]byte, []int) {
return file_controller_api_resources_roles_v1_role_proto_rawDescGZIP(), []int{0}
return file_controller_api_resources_roles_v1_role_proto_rawDescGZIP(), []int{2}
}
func (x *Role) GetId() string {
@@ -162,16 +270,16 @@ func (x *Role) GetVersion() uint32 {
return 0
}
func (x *Role) GetUserIds() []string {
func (x *Role) GetPrincipalIds() []string {
if x != nil {
return x.UserIds
return x.PrincipalIds
}
return nil
}
func (x *Role) GetGroupIds() []string {
func (x *Role) GetPrincipals() []*Principal {
if x != nil {
return x.GroupIds
return x.Principals
}
return nil
}
@@ -209,48 +317,57 @@ var file_controller_api_resources_roles_v1_role_proto_rawDesc = []byte{
0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x22, 0xbc, 0x04, 0x0a, 0x04, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69,
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x30, 0x0a, 0x04, 0x6e,
0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69,
0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3e, 0x0a,
0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65,
0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a,
0x0c, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52,
0x0c, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x3e, 0x0a,
0x0c, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x05, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52,
0x0c, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x36, 0x0a,
0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x08, 0x64, 0x69, 0x73,
0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x44, 0x0a, 0x0e, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x73,
0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e,
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0e, 0x67, 0x72, 0x61,
0x6e, 0x74, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76,
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65,
0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64,
0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x73,
0x12, 0x1b, 0x0a, 0x09, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x0a, 0x20,
0x03, 0x28, 0x09, 0x52, 0x08, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, 0x73, 0x12, 0x16, 0x0a,
0x06, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x67,
0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x5f,
0x63, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, 0x6c, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x09, 0x52,
0x0f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x43, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, 0x6c,
0x12, 0x1f, 0x0a, 0x0b, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18,
0x0d, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x4a, 0x73, 0x6f,
0x6e, 0x42, 0x53, 0x5a, 0x51, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x77, 0x61, 0x74, 0x63, 0x68, 0x74,
0x6f, 0x77, 0x65, 0x72, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65,
0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69,
0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73,
0x3b, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x74, 0x6f, 0x22, 0x4b, 0x0a, 0x09, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x12,
0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12,
0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74,
0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x18,
0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x22,
0x07, 0x0a, 0x05, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x22, 0xf8, 0x04, 0x0a, 0x04, 0x52, 0x6f, 0x6c,
0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69,
0x64, 0x12, 0x30, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x04, 0x6e,
0x61, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69,
0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e,
0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x0c, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74,
0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65,
0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0c, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74,
0x69, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x0c, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74,
0x69, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65,
0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0c, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74,
0x69, 0x6d, 0x65, 0x12, 0x36, 0x0a, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18,
0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75,
0x65, 0x52, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x44, 0x0a, 0x0e, 0x67,
0x72, 0x61, 0x6e, 0x74, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75,
0x65, 0x52, 0x0e, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69,
0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01,
0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x0d, 0x70,
0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x09, 0x20, 0x03,
0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x5f, 0x69, 0x64,
0x73, 0x12, 0x4c, 0x0a, 0x0a, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x18,
0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
0x2e, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69,
0x70, 0x61, 0x6c, 0x52, 0x0a, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x12,
0x16, 0x0a, 0x06, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x09, 0x52,
0x06, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x67, 0x72, 0x61, 0x6e, 0x74,
0x73, 0x5f, 0x63, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, 0x6c, 0x18, 0x0c, 0x20, 0x03, 0x28,
0x09, 0x52, 0x0f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x43, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63,
0x61, 0x6c, 0x12, 0x1f, 0x0a, 0x0b, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x5f, 0x6a, 0x73, 0x6f,
0x6e, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x4a,
0x73, 0x6f, 0x6e, 0x42, 0x53, 0x5a, 0x51, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f,
0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x77, 0x61, 0x74, 0x63,
0x68, 0x74, 0x6f, 0x77, 0x65, 0x72, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f,
0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61,
0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x72, 0x6f, 0x6c,
0x65, 0x73, 0x3b, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -265,25 +382,28 @@ func file_controller_api_resources_roles_v1_role_proto_rawDescGZIP() []byte {
return file_controller_api_resources_roles_v1_role_proto_rawDescData
}
var file_controller_api_resources_roles_v1_role_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_controller_api_resources_roles_v1_role_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
var file_controller_api_resources_roles_v1_role_proto_goTypes = []interface{}{
(*Role)(nil), // 0: controller.api.resources.roles.v1.Role
(*wrappers.StringValue)(nil), // 1: google.protobuf.StringValue
(*timestamp.Timestamp)(nil), // 2: google.protobuf.Timestamp
(*wrappers.BoolValue)(nil), // 3: google.protobuf.BoolValue
(*Principal)(nil), // 0: controller.api.resources.roles.v1.Principal
(*Grant)(nil), // 1: controller.api.resources.roles.v1.Grant
(*Role)(nil), // 2: controller.api.resources.roles.v1.Role
(*wrappers.StringValue)(nil), // 3: google.protobuf.StringValue
(*timestamp.Timestamp)(nil), // 4: google.protobuf.Timestamp
(*wrappers.BoolValue)(nil), // 5: google.protobuf.BoolValue
}
var file_controller_api_resources_roles_v1_role_proto_depIdxs = []int32{
1, // 0: controller.api.resources.roles.v1.Role.name:type_name -> google.protobuf.StringValue
1, // 1: controller.api.resources.roles.v1.Role.description:type_name -> google.protobuf.StringValue
2, // 2: controller.api.resources.roles.v1.Role.created_time:type_name -> google.protobuf.Timestamp
2, // 3: controller.api.resources.roles.v1.Role.updated_time:type_name -> google.protobuf.Timestamp
3, // 4: controller.api.resources.roles.v1.Role.disabled:type_name -> google.protobuf.BoolValue
1, // 5: controller.api.resources.roles.v1.Role.grant_scope_id:type_name -> google.protobuf.StringValue
6, // [6:6] is the sub-list for method output_type
6, // [6:6] is the sub-list for method input_type
6, // [6:6] is the sub-list for extension type_name
6, // [6:6] is the sub-list for extension extendee
0, // [0:6] is the sub-list for field type_name
3, // 0: controller.api.resources.roles.v1.Role.name:type_name -> google.protobuf.StringValue
3, // 1: controller.api.resources.roles.v1.Role.description:type_name -> google.protobuf.StringValue
4, // 2: controller.api.resources.roles.v1.Role.created_time:type_name -> google.protobuf.Timestamp
4, // 3: controller.api.resources.roles.v1.Role.updated_time:type_name -> google.protobuf.Timestamp
5, // 4: controller.api.resources.roles.v1.Role.disabled:type_name -> google.protobuf.BoolValue
3, // 5: controller.api.resources.roles.v1.Role.grant_scope_id:type_name -> google.protobuf.StringValue
0, // 6: controller.api.resources.roles.v1.Role.principals:type_name -> controller.api.resources.roles.v1.Principal
7, // [7:7] is the sub-list for method output_type
7, // [7:7] is the sub-list for method input_type
7, // [7:7] is the sub-list for extension type_name
7, // [7:7] is the sub-list for extension extendee
0, // [0:7] is the sub-list for field type_name
}
func init() { file_controller_api_resources_roles_v1_role_proto_init() }
@@ -293,6 +413,30 @@ func file_controller_api_resources_roles_v1_role_proto_init() {
}
if !protoimpl.UnsafeEnabled {
file_controller_api_resources_roles_v1_role_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Principal); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_controller_api_resources_roles_v1_role_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Grant); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_controller_api_resources_roles_v1_role_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Role); i {
case 0:
return &v.state
@@ -311,7 +455,7 @@ func file_controller_api_resources_roles_v1_role_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_controller_api_resources_roles_v1_role_proto_rawDesc,
NumEnums: 0,
NumMessages: 1,
NumMessages: 3,
NumExtensions: 0,
NumServices: 0,
},
@@ -0,0 +1,626 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.24.0
// protoc v3.12.3
// source: controller/api/services/v1/authenticate_service.proto
package services
import (
context "context"
proto "github.com/golang/protobuf/proto"
_struct "github.com/golang/protobuf/ptypes/struct"
_ "github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger/options"
authtokens "github.com/hashicorp/watchtower/internal/gen/controller/api/resources/authtokens"
_ "google.golang.org/genproto/googleapis/api/annotations"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// This is a compile-time assertion that a sufficiently up-to-date version
// of the legacy proto package is being used.
const _ = proto.ProtoPackageIsVersion4
// The layout of the struct for "credentials" field in AuthenticateRequest. This message isn't
// directly referenced anywhere but is used here to define the expected field names and types.
type PasswordCredentials struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"`
}
func (x *PasswordCredentials) Reset() {
*x = PasswordCredentials{}
if protoimpl.UnsafeEnabled {
mi := &file_controller_api_services_v1_authenticate_service_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *PasswordCredentials) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*PasswordCredentials) ProtoMessage() {}
func (x *PasswordCredentials) ProtoReflect() protoreflect.Message {
mi := &file_controller_api_services_v1_authenticate_service_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use PasswordCredentials.ProtoReflect.Descriptor instead.
func (*PasswordCredentials) Descriptor() ([]byte, []int) {
return file_controller_api_services_v1_authenticate_service_proto_rawDescGZIP(), []int{0}
}
func (x *PasswordCredentials) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *PasswordCredentials) GetPassword() string {
if x != nil {
return x.Password
}
return ""
}
type AuthenticateRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
OrgId string `protobuf:"bytes,1,opt,name=org_id,json=orgId,proto3" json:"org_id,omitempty"`
// The id to the authmethod in the system being used for authentication. The auth method must be in the org
// being logged in to.
AuthMethodId string `protobuf:"bytes,2,opt,name=auth_method_id,json=authMethodId,proto3" json:"auth_method_id,omitempty"`
// This can be "cookie" or "token". If not provided, "token" will be used. For now only type "token" is returned.
TokenType string `protobuf:"bytes,3,opt,name=token_type,json=tokenType,proto3" json:"token_type,omitempty"`
// credentials are the different possible credential names depending on what type of auth method is used.
// For password auth method: should include only "name" and "password".
Credentials *_struct.Struct `protobuf:"bytes,8,opt,name=credentials,proto3" json:"credentials,omitempty"`
}
func (x *AuthenticateRequest) Reset() {
*x = AuthenticateRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_controller_api_services_v1_authenticate_service_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *AuthenticateRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*AuthenticateRequest) ProtoMessage() {}
func (x *AuthenticateRequest) ProtoReflect() protoreflect.Message {
mi := &file_controller_api_services_v1_authenticate_service_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use AuthenticateRequest.ProtoReflect.Descriptor instead.
func (*AuthenticateRequest) Descriptor() ([]byte, []int) {
return file_controller_api_services_v1_authenticate_service_proto_rawDescGZIP(), []int{1}
}
func (x *AuthenticateRequest) GetOrgId() string {
if x != nil {
return x.OrgId
}
return ""
}
func (x *AuthenticateRequest) GetAuthMethodId() string {
if x != nil {
return x.AuthMethodId
}
return ""
}
func (x *AuthenticateRequest) GetTokenType() string {
if x != nil {
return x.TokenType
}
return ""
}
func (x *AuthenticateRequest) GetCredentials() *_struct.Struct {
if x != nil {
return x.Credentials
}
return nil
}
type AuthenticateResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Item *authtokens.AuthToken `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"`
}
func (x *AuthenticateResponse) Reset() {
*x = AuthenticateResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_controller_api_services_v1_authenticate_service_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *AuthenticateResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*AuthenticateResponse) ProtoMessage() {}
func (x *AuthenticateResponse) ProtoReflect() protoreflect.Message {
mi := &file_controller_api_services_v1_authenticate_service_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use AuthenticateResponse.ProtoReflect.Descriptor instead.
func (*AuthenticateResponse) Descriptor() ([]byte, []int) {
return file_controller_api_services_v1_authenticate_service_proto_rawDescGZIP(), []int{2}
}
func (x *AuthenticateResponse) GetItem() *authtokens.AuthToken {
if x != nil {
return x.Item
}
return nil
}
type DeauthenticateRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
OrgId string `protobuf:"bytes,1,opt,name=org_id,json=orgId,proto3" json:"org_id,omitempty"`
}
func (x *DeauthenticateRequest) Reset() {
*x = DeauthenticateRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_controller_api_services_v1_authenticate_service_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DeauthenticateRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DeauthenticateRequest) ProtoMessage() {}
func (x *DeauthenticateRequest) ProtoReflect() protoreflect.Message {
mi := &file_controller_api_services_v1_authenticate_service_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DeauthenticateRequest.ProtoReflect.Descriptor instead.
func (*DeauthenticateRequest) Descriptor() ([]byte, []int) {
return file_controller_api_services_v1_authenticate_service_proto_rawDescGZIP(), []int{3}
}
func (x *DeauthenticateRequest) GetOrgId() string {
if x != nil {
return x.OrgId
}
return ""
}
type DeauthenticateResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *DeauthenticateResponse) Reset() {
*x = DeauthenticateResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_controller_api_services_v1_authenticate_service_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DeauthenticateResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DeauthenticateResponse) ProtoMessage() {}
func (x *DeauthenticateResponse) ProtoReflect() protoreflect.Message {
mi := &file_controller_api_services_v1_authenticate_service_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DeauthenticateResponse.ProtoReflect.Descriptor instead.
func (*DeauthenticateResponse) Descriptor() ([]byte, []int) {
return file_controller_api_services_v1_authenticate_service_proto_rawDescGZIP(), []int{4}
}
var File_controller_api_services_v1_authenticate_service_proto protoreflect.FileDescriptor
var file_controller_api_services_v1_authenticate_service_proto_rawDesc = []byte{
0x0a, 0x35, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69,
0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x75, 0x74,
0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1a, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73,
0x2e, 0x76, 0x31, 0x1a, 0x2c, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d,
0x73, 0x77, 0x61, 0x67, 0x67, 0x65, 0x72, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f,
0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e,
0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x36, 0x63,
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65,
0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x74, 0x6f, 0x6b, 0x65,
0x6e, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x45, 0x0a, 0x13, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72,
0x64, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x12, 0x12, 0x0a, 0x04,
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0xac, 0x01, 0x0a,
0x13, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6f, 0x72, 0x67, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x61,
0x75, 0x74, 0x68, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20,
0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x49,
0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18,
0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x54, 0x79, 0x70, 0x65,
0x12, 0x39, 0x0a, 0x0b, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x18,
0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x0b,
0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x22, 0x5d, 0x0a, 0x14, 0x41,
0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61,
0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x61, 0x75, 0x74,
0x68, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x54,
0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0x2e, 0x0a, 0x15, 0x44, 0x65,
0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x05, 0x6f, 0x72, 0x67, 0x49, 0x64, 0x22, 0x18, 0x0a, 0x16, 0x44, 0x65,
0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x32, 0xff, 0x03, 0x0a, 0x15, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74,
0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x89,
0x02, 0x0a, 0x0c, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12,
0x2f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69,
0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74,
0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70,
0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75,
0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x22, 0x95, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x47, 0x22, 0x3c, 0x2f, 0x76, 0x31,
0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x61,
0x75, 0x74, 0x68, 0x2d, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x2f, 0x7b, 0x61, 0x75, 0x74,
0x68, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x69, 0x64, 0x7d, 0x3a, 0x61, 0x75, 0x74,
0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74,
0x65, 0x6d, 0x92, 0x41, 0x45, 0x12, 0x43, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63,
0x61, 0x74, 0x65, 0x20, 0x61, 0x20, 0x75, 0x73, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6e,
0x20, 0x4f, 0x72, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76,
0x65, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x2e, 0x12, 0xd9, 0x01, 0x0a, 0x0e, 0x44,
0x65, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x31, 0x2e,
0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73,
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x61, 0x75, 0x74,
0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70,
0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65,
0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x60, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x22, 0x20, 0x2f, 0x76,
0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x3a,
0x64, 0x65, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x92, 0x41,
0x35, 0x12, 0x33, 0x44, 0x65, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74,
0x65, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61,
0x6e, 0x20, 0x4f, 0x72, 0x67, 0x2e, 0x42, 0x4f, 0x5a, 0x4d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x77,
0x61, 0x74, 0x63, 0x68, 0x74, 0x6f, 0x77, 0x65, 0x72, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e,
0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65,
0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x3b, 0x73,
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_controller_api_services_v1_authenticate_service_proto_rawDescOnce sync.Once
file_controller_api_services_v1_authenticate_service_proto_rawDescData = file_controller_api_services_v1_authenticate_service_proto_rawDesc
)
func file_controller_api_services_v1_authenticate_service_proto_rawDescGZIP() []byte {
file_controller_api_services_v1_authenticate_service_proto_rawDescOnce.Do(func() {
file_controller_api_services_v1_authenticate_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_controller_api_services_v1_authenticate_service_proto_rawDescData)
})
return file_controller_api_services_v1_authenticate_service_proto_rawDescData
}
var file_controller_api_services_v1_authenticate_service_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
var file_controller_api_services_v1_authenticate_service_proto_goTypes = []interface{}{
(*PasswordCredentials)(nil), // 0: controller.api.services.v1.PasswordCredentials
(*AuthenticateRequest)(nil), // 1: controller.api.services.v1.AuthenticateRequest
(*AuthenticateResponse)(nil), // 2: controller.api.services.v1.AuthenticateResponse
(*DeauthenticateRequest)(nil), // 3: controller.api.services.v1.DeauthenticateRequest
(*DeauthenticateResponse)(nil), // 4: controller.api.services.v1.DeauthenticateResponse
(*_struct.Struct)(nil), // 5: google.protobuf.Struct
(*authtokens.AuthToken)(nil), // 6: controller.api.resources.authtokens.v1.AuthToken
}
var file_controller_api_services_v1_authenticate_service_proto_depIdxs = []int32{
5, // 0: controller.api.services.v1.AuthenticateRequest.credentials:type_name -> google.protobuf.Struct
6, // 1: controller.api.services.v1.AuthenticateResponse.item:type_name -> controller.api.resources.authtokens.v1.AuthToken
1, // 2: controller.api.services.v1.AuthenticationService.Authenticate:input_type -> controller.api.services.v1.AuthenticateRequest
3, // 3: controller.api.services.v1.AuthenticationService.Deauthenticate:input_type -> controller.api.services.v1.DeauthenticateRequest
2, // 4: controller.api.services.v1.AuthenticationService.Authenticate:output_type -> controller.api.services.v1.AuthenticateResponse
4, // 5: controller.api.services.v1.AuthenticationService.Deauthenticate:output_type -> controller.api.services.v1.DeauthenticateResponse
4, // [4:6] is the sub-list for method output_type
2, // [2:4] is the sub-list for method input_type
2, // [2:2] is the sub-list for extension type_name
2, // [2:2] is the sub-list for extension extendee
0, // [0:2] is the sub-list for field type_name
}
func init() { file_controller_api_services_v1_authenticate_service_proto_init() }
func file_controller_api_services_v1_authenticate_service_proto_init() {
if File_controller_api_services_v1_authenticate_service_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_controller_api_services_v1_authenticate_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*PasswordCredentials); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_controller_api_services_v1_authenticate_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*AuthenticateRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_controller_api_services_v1_authenticate_service_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*AuthenticateResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_controller_api_services_v1_authenticate_service_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DeauthenticateRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_controller_api_services_v1_authenticate_service_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DeauthenticateResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_controller_api_services_v1_authenticate_service_proto_rawDesc,
NumEnums: 0,
NumMessages: 5,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_controller_api_services_v1_authenticate_service_proto_goTypes,
DependencyIndexes: file_controller_api_services_v1_authenticate_service_proto_depIdxs,
MessageInfos: file_controller_api_services_v1_authenticate_service_proto_msgTypes,
}.Build()
File_controller_api_services_v1_authenticate_service_proto = out.File
file_controller_api_services_v1_authenticate_service_proto_rawDesc = nil
file_controller_api_services_v1_authenticate_service_proto_goTypes = nil
file_controller_api_services_v1_authenticate_service_proto_depIdxs = nil
}
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConnInterface
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion6
// AuthenticationServiceClient is the client API for AuthenticationService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type AuthenticationServiceClient interface {
// Authenticate validates credentials provided and returns an auth token.
Authenticate(ctx context.Context, in *AuthenticateRequest, opts ...grpc.CallOption) (*AuthenticateResponse, error)
// Logout terminates a user's current session.
Deauthenticate(ctx context.Context, in *DeauthenticateRequest, opts ...grpc.CallOption) (*DeauthenticateResponse, error)
}
type authenticationServiceClient struct {
cc grpc.ClientConnInterface
}
func NewAuthenticationServiceClient(cc grpc.ClientConnInterface) AuthenticationServiceClient {
return &authenticationServiceClient{cc}
}
func (c *authenticationServiceClient) Authenticate(ctx context.Context, in *AuthenticateRequest, opts ...grpc.CallOption) (*AuthenticateResponse, error) {
out := new(AuthenticateResponse)
err := c.cc.Invoke(ctx, "/controller.api.services.v1.AuthenticationService/Authenticate", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *authenticationServiceClient) Deauthenticate(ctx context.Context, in *DeauthenticateRequest, opts ...grpc.CallOption) (*DeauthenticateResponse, error) {
out := new(DeauthenticateResponse)
err := c.cc.Invoke(ctx, "/controller.api.services.v1.AuthenticationService/Deauthenticate", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// AuthenticationServiceServer is the server API for AuthenticationService service.
type AuthenticationServiceServer interface {
// Authenticate validates credentials provided and returns an auth token.
Authenticate(context.Context, *AuthenticateRequest) (*AuthenticateResponse, error)
// Logout terminates a user's current session.
Deauthenticate(context.Context, *DeauthenticateRequest) (*DeauthenticateResponse, error)
}
// UnimplementedAuthenticationServiceServer can be embedded to have forward compatible implementations.
type UnimplementedAuthenticationServiceServer struct {
}
func (*UnimplementedAuthenticationServiceServer) Authenticate(context.Context, *AuthenticateRequest) (*AuthenticateResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Authenticate not implemented")
}
func (*UnimplementedAuthenticationServiceServer) Deauthenticate(context.Context, *DeauthenticateRequest) (*DeauthenticateResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Deauthenticate not implemented")
}
func RegisterAuthenticationServiceServer(s *grpc.Server, srv AuthenticationServiceServer) {
s.RegisterService(&_AuthenticationService_serviceDesc, srv)
}
func _AuthenticationService_Authenticate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(AuthenticateRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AuthenticationServiceServer).Authenticate(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/controller.api.services.v1.AuthenticationService/Authenticate",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AuthenticationServiceServer).Authenticate(ctx, req.(*AuthenticateRequest))
}
return interceptor(ctx, in, info, handler)
}
func _AuthenticationService_Deauthenticate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DeauthenticateRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AuthenticationServiceServer).Deauthenticate(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/controller.api.services.v1.AuthenticationService/Deauthenticate",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AuthenticationServiceServer).Deauthenticate(ctx, req.(*DeauthenticateRequest))
}
return interceptor(ctx, in, info, handler)
}
var _AuthenticationService_serviceDesc = grpc.ServiceDesc{
ServiceName: "controller.api.services.v1.AuthenticationService",
HandlerType: (*AuthenticationServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Authenticate",
Handler: _AuthenticationService_Authenticate_Handler,
},
{
MethodName: "Deauthenticate",
Handler: _AuthenticationService_Deauthenticate_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "controller/api/services/v1/authenticate_service.proto",
}
@@ -0,0 +1,328 @@
// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT.
// source: controller/api/services/v1/authenticate_service.proto
/*
Package services is a reverse proxy.
It translates gRPC into RESTful JSON APIs.
*/
package services
import (
"context"
"io"
"net/http"
"github.com/golang/protobuf/descriptor"
"github.com/golang/protobuf/proto"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
"github.com/grpc-ecosystem/grpc-gateway/utilities"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/grpclog"
"google.golang.org/grpc/status"
)
// Suppress "imported and not used" errors
var _ codes.Code
var _ io.Reader
var _ status.Status
var _ = runtime.String
var _ = utilities.NewDoubleArray
var _ = descriptor.ForMessage
func request_AuthenticationService_Authenticate_0(ctx context.Context, marshaler runtime.Marshaler, client AuthenticationServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq AuthenticateRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["org_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "org_id")
}
protoReq.OrgId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err)
}
val, ok = pathParams["auth_method_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "auth_method_id")
}
protoReq.AuthMethodId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "auth_method_id", err)
}
msg, err := client.Authenticate(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_AuthenticationService_Authenticate_0(ctx context.Context, marshaler runtime.Marshaler, server AuthenticationServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq AuthenticateRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["org_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "org_id")
}
protoReq.OrgId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err)
}
val, ok = pathParams["auth_method_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "auth_method_id")
}
protoReq.AuthMethodId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "auth_method_id", err)
}
msg, err := server.Authenticate(ctx, &protoReq)
return msg, metadata, err
}
func request_AuthenticationService_Deauthenticate_0(ctx context.Context, marshaler runtime.Marshaler, client AuthenticationServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq DeauthenticateRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["org_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "org_id")
}
protoReq.OrgId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err)
}
msg, err := client.Deauthenticate(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_AuthenticationService_Deauthenticate_0(ctx context.Context, marshaler runtime.Marshaler, server AuthenticationServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq DeauthenticateRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["org_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "org_id")
}
protoReq.OrgId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err)
}
msg, err := server.Deauthenticate(ctx, &protoReq)
return msg, metadata, err
}
// RegisterAuthenticationServiceHandlerServer registers the http handlers for service AuthenticationService to "mux".
// UnaryRPC :call AuthenticationServiceServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
func RegisterAuthenticationServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server AuthenticationServiceServer) error {
mux.Handle("POST", pattern_AuthenticationService_Authenticate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_AuthenticationService_Authenticate_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_AuthenticationService_Authenticate_0(ctx, mux, outboundMarshaler, w, req, response_AuthenticationService_Authenticate_0{resp}, mux.GetForwardResponseOptions()...)
})
mux.Handle("POST", pattern_AuthenticationService_Deauthenticate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_AuthenticationService_Deauthenticate_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_AuthenticationService_Deauthenticate_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
// RegisterAuthenticationServiceHandlerFromEndpoint is same as RegisterAuthenticationServiceHandler but
// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
func RegisterAuthenticationServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
conn, err := grpc.Dial(endpoint, opts...)
if err != nil {
return err
}
defer func() {
if err != nil {
if cerr := conn.Close(); cerr != nil {
grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
}
return
}
go func() {
<-ctx.Done()
if cerr := conn.Close(); cerr != nil {
grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
}
}()
}()
return RegisterAuthenticationServiceHandler(ctx, mux, conn)
}
// RegisterAuthenticationServiceHandler registers the http handlers for service AuthenticationService to "mux".
// The handlers forward requests to the grpc endpoint over "conn".
func RegisterAuthenticationServiceHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
return RegisterAuthenticationServiceHandlerClient(ctx, mux, NewAuthenticationServiceClient(conn))
}
// RegisterAuthenticationServiceHandlerClient registers the http handlers for service AuthenticationService
// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "AuthenticationServiceClient".
// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "AuthenticationServiceClient"
// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
// "AuthenticationServiceClient" to call the correct interceptors.
func RegisterAuthenticationServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client AuthenticationServiceClient) error {
mux.Handle("POST", pattern_AuthenticationService_Authenticate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_AuthenticationService_Authenticate_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_AuthenticationService_Authenticate_0(ctx, mux, outboundMarshaler, w, req, response_AuthenticationService_Authenticate_0{resp}, mux.GetForwardResponseOptions()...)
})
mux.Handle("POST", pattern_AuthenticationService_Deauthenticate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_AuthenticationService_Deauthenticate_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_AuthenticationService_Deauthenticate_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
type response_AuthenticationService_Authenticate_0 struct {
proto.Message
}
func (m response_AuthenticationService_Authenticate_0) XXX_ResponseBody() interface{} {
response := m.Message.(*AuthenticateResponse)
return response.Item
}
var (
pattern_AuthenticationService_Authenticate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"v1", "orgs", "org_id", "auth-methods", "auth_method_id"}, "authenticate", runtime.AssumeColonVerbOpt(true)))
pattern_AuthenticationService_Deauthenticate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "orgs", "org_id"}, "deauthenticate", runtime.AssumeColonVerbOpt(true)))
)
var (
forward_AuthenticationService_Authenticate_0 = runtime.ForwardResponseMessage
forward_AuthenticationService_Deauthenticate_0 = runtime.ForwardResponseMessage
)
@@ -10,7 +10,6 @@ import (
context "context"
proto "github.com/golang/protobuf/proto"
_ "github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger/options"
authtokens "github.com/hashicorp/watchtower/internal/gen/controller/api/resources/authtokens"
scopes "github.com/hashicorp/watchtower/internal/gen/controller/api/resources/scopes"
_ "google.golang.org/genproto/googleapis/api/annotations"
grpc "google.golang.org/grpc"
@@ -229,267 +228,6 @@ func (x *ListOrgsResponse) GetItems() []*scopes.Org {
return nil
}
type PasswordCredential struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
LoginName string `protobuf:"bytes,1,opt,name=login_name,json=loginName,proto3" json:"login_name,omitempty"`
Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"`
}
func (x *PasswordCredential) Reset() {
*x = PasswordCredential{}
if protoimpl.UnsafeEnabled {
mi := &file_controller_api_services_v1_org_service_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *PasswordCredential) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*PasswordCredential) ProtoMessage() {}
func (x *PasswordCredential) ProtoReflect() protoreflect.Message {
mi := &file_controller_api_services_v1_org_service_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use PasswordCredential.ProtoReflect.Descriptor instead.
func (*PasswordCredential) Descriptor() ([]byte, []int) {
return file_controller_api_services_v1_org_service_proto_rawDescGZIP(), []int{4}
}
func (x *PasswordCredential) GetLoginName() string {
if x != nil {
return x.LoginName
}
return ""
}
func (x *PasswordCredential) GetPassword() string {
if x != nil {
return x.Password
}
return ""
}
type AuthenticateRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
OrgId string `protobuf:"bytes,1,opt,name=org_id,json=orgId,proto3" json:"org_id,omitempty"`
// The id to the authmethod in the system being used for authentication. The auth method must be in the org
// being logged in to.
AuthMethodId string `protobuf:"bytes,2,opt,name=auth_method_id,json=authMethodId,proto3" json:"auth_method_id,omitempty"`
// This can be "cookie" or "token". If not provided, "token" will be used. For now only type "token" is returned.
TokenType string `protobuf:"bytes,3,opt,name=token_type,json=tokenType,proto3" json:"token_type,omitempty"`
PasswordCredential *PasswordCredential `protobuf:"bytes,4,opt,name=password_credential,json=passwordCredential,proto3" json:"password_credential,omitempty"`
}
func (x *AuthenticateRequest) Reset() {
*x = AuthenticateRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_controller_api_services_v1_org_service_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *AuthenticateRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*AuthenticateRequest) ProtoMessage() {}
func (x *AuthenticateRequest) ProtoReflect() protoreflect.Message {
mi := &file_controller_api_services_v1_org_service_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use AuthenticateRequest.ProtoReflect.Descriptor instead.
func (*AuthenticateRequest) Descriptor() ([]byte, []int) {
return file_controller_api_services_v1_org_service_proto_rawDescGZIP(), []int{5}
}
func (x *AuthenticateRequest) GetOrgId() string {
if x != nil {
return x.OrgId
}
return ""
}
func (x *AuthenticateRequest) GetAuthMethodId() string {
if x != nil {
return x.AuthMethodId
}
return ""
}
func (x *AuthenticateRequest) GetTokenType() string {
if x != nil {
return x.TokenType
}
return ""
}
func (x *AuthenticateRequest) GetPasswordCredential() *PasswordCredential {
if x != nil {
return x.PasswordCredential
}
return nil
}
type AuthenticateResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Item *authtokens.AuthToken `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"`
}
func (x *AuthenticateResponse) Reset() {
*x = AuthenticateResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_controller_api_services_v1_org_service_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *AuthenticateResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*AuthenticateResponse) ProtoMessage() {}
func (x *AuthenticateResponse) ProtoReflect() protoreflect.Message {
mi := &file_controller_api_services_v1_org_service_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use AuthenticateResponse.ProtoReflect.Descriptor instead.
func (*AuthenticateResponse) Descriptor() ([]byte, []int) {
return file_controller_api_services_v1_org_service_proto_rawDescGZIP(), []int{6}
}
func (x *AuthenticateResponse) GetItem() *authtokens.AuthToken {
if x != nil {
return x.Item
}
return nil
}
type DeauthenticateRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
OrgId string `protobuf:"bytes,1,opt,name=org_id,json=orgId,proto3" json:"org_id,omitempty"`
}
func (x *DeauthenticateRequest) Reset() {
*x = DeauthenticateRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_controller_api_services_v1_org_service_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DeauthenticateRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DeauthenticateRequest) ProtoMessage() {}
func (x *DeauthenticateRequest) ProtoReflect() protoreflect.Message {
mi := &file_controller_api_services_v1_org_service_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DeauthenticateRequest.ProtoReflect.Descriptor instead.
func (*DeauthenticateRequest) Descriptor() ([]byte, []int) {
return file_controller_api_services_v1_org_service_proto_rawDescGZIP(), []int{7}
}
func (x *DeauthenticateRequest) GetOrgId() string {
if x != nil {
return x.OrgId
}
return ""
}
type DeauthenticateResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *DeauthenticateResponse) Reset() {
*x = DeauthenticateResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_controller_api_services_v1_org_service_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DeauthenticateResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DeauthenticateResponse) ProtoMessage() {}
func (x *DeauthenticateResponse) ProtoReflect() protoreflect.Message {
mi := &file_controller_api_services_v1_org_service_proto_msgTypes[8]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DeauthenticateResponse.ProtoReflect.Descriptor instead.
func (*DeauthenticateResponse) Descriptor() ([]byte, []int) {
return file_controller_api_services_v1_org_service_proto_rawDescGZIP(), []int{8}
}
var File_controller_api_services_v1_org_service_proto protoreflect.FileDescriptor
var file_controller_api_services_v1_org_service_proto_rawDesc = []byte{
@@ -505,103 +243,42 @@ var file_controller_api_services_v1_org_service_proto_rawDesc = []byte{
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2c, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x36, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72,
0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x61,
0x75, 0x74, 0x68, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x75, 0x74,
0x68, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x33, 0x0a, 0x0d,
0x47, 0x65, 0x74, 0x4f, 0x72, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a,
0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a,
0x04, 0x76, 0x69, 0x65, 0x77, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x76, 0x69, 0x65,
0x77, 0x22, 0x4d, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61,
0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x63, 0x6f,
0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x72, 0x67, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d,
0x22, 0x25, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x72, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x76, 0x69, 0x65, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x04, 0x76, 0x69, 0x65, 0x77, 0x22, 0x51, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x4f,
0x72, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x05, 0x69,
0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x63, 0x6f, 0x6e,
0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f,
0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e,
0x4f, 0x72, 0x67, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x22, 0x4f, 0x0a, 0x12, 0x50, 0x61,
0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c,
0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12,
0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28,
0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0xd2, 0x01, 0x0a, 0x13,
0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x05, 0x6f, 0x72, 0x67, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x61, 0x75,
0x74, 0x68, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x0c, 0x61, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x49, 0x64,
0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03,
0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12,
0x5f, 0x0a, 0x13, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x63, 0x72, 0x65, 0x64,
0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x63,
0x72, 0x6f, 0x74, 0x6f, 0x22, 0x33, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x67, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x76, 0x69, 0x65, 0x77, 0x18, 0x02, 0x20,
0x01, 0x28, 0x09, 0x52, 0x04, 0x76, 0x69, 0x65, 0x77, 0x22, 0x4d, 0x0a, 0x0e, 0x47, 0x65, 0x74,
0x4f, 0x72, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x04, 0x69,
0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74,
0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75,
0x72, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4f,
0x72, 0x67, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0x25, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74,
0x4f, 0x72, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x76,
0x69, 0x65, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x76, 0x69, 0x65, 0x77, 0x22,
0x51, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x72, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03,
0x28, 0x0b, 0x32, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e,
0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x63,
0x6f, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x72, 0x67, 0x52, 0x05, 0x69, 0x74, 0x65,
0x6d, 0x73, 0x32, 0xae, 0x02, 0x0a, 0x0a, 0x4f, 0x72, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
0x65, 0x12, 0x92, 0x01, 0x0a, 0x06, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x67, 0x12, 0x29, 0x2e, 0x63,
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f,
0x72, 0x64, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x12, 0x70, 0x61,
0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c,
0x22, 0x5d, 0x0a, 0x14, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
0x73, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e,
0x41, 0x75, 0x74, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22,
0x2e, 0x0a, 0x15, 0x44, 0x65, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74,
0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x6f, 0x72, 0x67, 0x5f,
0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6f, 0x72, 0x67, 0x49, 0x64, 0x22,
0x18, 0x0a, 0x16, 0x44, 0x65, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74,
0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xf7, 0x05, 0x0a, 0x0a, 0x4f, 0x72,
0x67, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x92, 0x01, 0x0a, 0x06, 0x47, 0x65, 0x74,
0x4f, 0x72, 0x67, 0x12, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72,
0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31,
0x2e, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a,
0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e,
0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4f,
0x72, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x31, 0x82, 0xd3, 0xe4, 0x93,
0x02, 0x15, 0x12, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x69, 0x64,
0x7d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x13, 0x12, 0x11, 0x47, 0x65, 0x74, 0x73,
0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x4f, 0x72, 0x67, 0x12, 0x8a, 0x01,
0x0a, 0x08, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x72, 0x67, 0x73, 0x12, 0x2b, 0x2e, 0x63, 0x6f, 0x6e,
0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76,
0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x72, 0x67, 0x73,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x67,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x72, 0x67, 0x73, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0a, 0x12, 0x08, 0x2f,
0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x92, 0x41, 0x10, 0x12, 0x0e, 0x4c, 0x69, 0x73, 0x74,
0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x4f, 0x72, 0x67, 0x73, 0x12, 0xea, 0x01, 0x0a, 0x0c, 0x41,
0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x2f, 0x2e, 0x63, 0x6f,
0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72,
0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74,
0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x63,
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e,
0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x77,
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29, 0x22, 0x1e, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73,
0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x3a, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e,
0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92,
0x41, 0x45, 0x12, 0x43, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65,
0x20, 0x61, 0x20, 0x75, 0x73, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6e, 0x20, 0x4f, 0x72,
0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x20, 0x61,
0x6e, 0x20, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x20, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x2e, 0x12, 0xd9, 0x01, 0x0a, 0x0e, 0x44, 0x65, 0x61, 0x75,
0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x31, 0x2e, 0x63, 0x6f, 0x6e,
0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76,
0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e,
0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e,
0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73,
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x61, 0x75, 0x74,
0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x22, 0x60, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x22, 0x20, 0x2f, 0x76, 0x31, 0x2f, 0x6f,
0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x3a, 0x64, 0x65, 0x61,
0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x92, 0x41, 0x35, 0x12, 0x33,
0x44, 0x65, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x61,
0x6e, 0x20, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x20, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61, 0x6e, 0x20, 0x4f,
0x72, 0x67, 0x2e, 0x42, 0x4f, 0x5a, 0x4d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f,
0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x22, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x0d, 0x2f, 0x76, 0x31,
0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d,
0x92, 0x41, 0x13, 0x12, 0x11, 0x47, 0x65, 0x74, 0x73, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67,
0x6c, 0x65, 0x20, 0x4f, 0x72, 0x67, 0x12, 0x8a, 0x01, 0x0a, 0x08, 0x4c, 0x69, 0x73, 0x74, 0x4f,
0x72, 0x67, 0x73, 0x12, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72,
0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31,
0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x72, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x2c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70,
0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69,
0x73, 0x74, 0x4f, 0x72, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23,
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0a, 0x12, 0x08, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73,
0x92, 0x41, 0x10, 0x12, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x4f,
0x72, 0x67, 0x73, 0x42, 0x4f, 0x5a, 0x4d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f,
0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x77, 0x61, 0x74, 0x63,
0x68, 0x74, 0x6f, 0x77, 0x65, 0x72, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f,
0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61,
@@ -621,38 +298,26 @@ func file_controller_api_services_v1_org_service_proto_rawDescGZIP() []byte {
return file_controller_api_services_v1_org_service_proto_rawDescData
}
var file_controller_api_services_v1_org_service_proto_msgTypes = make([]protoimpl.MessageInfo, 9)
var file_controller_api_services_v1_org_service_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_controller_api_services_v1_org_service_proto_goTypes = []interface{}{
(*GetOrgRequest)(nil), // 0: controller.api.services.v1.GetOrgRequest
(*GetOrgResponse)(nil), // 1: controller.api.services.v1.GetOrgResponse
(*ListOrgsRequest)(nil), // 2: controller.api.services.v1.ListOrgsRequest
(*ListOrgsResponse)(nil), // 3: controller.api.services.v1.ListOrgsResponse
(*PasswordCredential)(nil), // 4: controller.api.services.v1.PasswordCredential
(*AuthenticateRequest)(nil), // 5: controller.api.services.v1.AuthenticateRequest
(*AuthenticateResponse)(nil), // 6: controller.api.services.v1.AuthenticateResponse
(*DeauthenticateRequest)(nil), // 7: controller.api.services.v1.DeauthenticateRequest
(*DeauthenticateResponse)(nil), // 8: controller.api.services.v1.DeauthenticateResponse
(*scopes.Org)(nil), // 9: controller.api.resources.scopes.v1.Org
(*authtokens.AuthToken)(nil), // 10: controller.api.resources.authtokens.v1.AuthToken
(*GetOrgRequest)(nil), // 0: controller.api.services.v1.GetOrgRequest
(*GetOrgResponse)(nil), // 1: controller.api.services.v1.GetOrgResponse
(*ListOrgsRequest)(nil), // 2: controller.api.services.v1.ListOrgsRequest
(*ListOrgsResponse)(nil), // 3: controller.api.services.v1.ListOrgsResponse
(*scopes.Org)(nil), // 4: controller.api.resources.scopes.v1.Org
}
var file_controller_api_services_v1_org_service_proto_depIdxs = []int32{
9, // 0: controller.api.services.v1.GetOrgResponse.item:type_name -> controller.api.resources.scopes.v1.Org
9, // 1: controller.api.services.v1.ListOrgsResponse.items:type_name -> controller.api.resources.scopes.v1.Org
4, // 2: controller.api.services.v1.AuthenticateRequest.password_credential:type_name -> controller.api.services.v1.PasswordCredential
10, // 3: controller.api.services.v1.AuthenticateResponse.item:type_name -> controller.api.resources.authtokens.v1.AuthToken
0, // 4: controller.api.services.v1.OrgService.GetOrg:input_type -> controller.api.services.v1.GetOrgRequest
2, // 5: controller.api.services.v1.OrgService.ListOrgs:input_type -> controller.api.services.v1.ListOrgsRequest
5, // 6: controller.api.services.v1.OrgService.Authenticate:input_type -> controller.api.services.v1.AuthenticateRequest
7, // 7: controller.api.services.v1.OrgService.Deauthenticate:input_type -> controller.api.services.v1.DeauthenticateRequest
1, // 8: controller.api.services.v1.OrgService.GetOrg:output_type -> controller.api.services.v1.GetOrgResponse
3, // 9: controller.api.services.v1.OrgService.ListOrgs:output_type -> controller.api.services.v1.ListOrgsResponse
6, // 10: controller.api.services.v1.OrgService.Authenticate:output_type -> controller.api.services.v1.AuthenticateResponse
8, // 11: controller.api.services.v1.OrgService.Deauthenticate:output_type -> controller.api.services.v1.DeauthenticateResponse
8, // [8:12] is the sub-list for method output_type
4, // [4:8] is the sub-list for method input_type
4, // [4:4] is the sub-list for extension type_name
4, // [4:4] is the sub-list for extension extendee
0, // [0:4] is the sub-list for field type_name
4, // 0: controller.api.services.v1.GetOrgResponse.item:type_name -> controller.api.resources.scopes.v1.Org
4, // 1: controller.api.services.v1.ListOrgsResponse.items:type_name -> controller.api.resources.scopes.v1.Org
0, // 2: controller.api.services.v1.OrgService.GetOrg:input_type -> controller.api.services.v1.GetOrgRequest
2, // 3: controller.api.services.v1.OrgService.ListOrgs:input_type -> controller.api.services.v1.ListOrgsRequest
1, // 4: controller.api.services.v1.OrgService.GetOrg:output_type -> controller.api.services.v1.GetOrgResponse
3, // 5: controller.api.services.v1.OrgService.ListOrgs:output_type -> controller.api.services.v1.ListOrgsResponse
4, // [4:6] is the sub-list for method output_type
2, // [2:4] is the sub-list for method input_type
2, // [2:2] is the sub-list for extension type_name
2, // [2:2] is the sub-list for extension extendee
0, // [0:2] is the sub-list for field type_name
}
func init() { file_controller_api_services_v1_org_service_proto_init() }
@@ -709,66 +374,6 @@ func file_controller_api_services_v1_org_service_proto_init() {
return nil
}
}
file_controller_api_services_v1_org_service_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*PasswordCredential); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_controller_api_services_v1_org_service_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*AuthenticateRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_controller_api_services_v1_org_service_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*AuthenticateResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_controller_api_services_v1_org_service_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DeauthenticateRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_controller_api_services_v1_org_service_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DeauthenticateResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
@@ -776,7 +381,7 @@ func file_controller_api_services_v1_org_service_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_controller_api_services_v1_org_service_proto_rawDesc,
NumEnums: 0,
NumMessages: 9,
NumMessages: 4,
NumExtensions: 0,
NumServices: 1,
},
@@ -808,10 +413,6 @@ type OrgServiceClient interface {
GetOrg(ctx context.Context, in *GetOrgRequest, opts ...grpc.CallOption) (*GetOrgResponse, error)
// ListOrgs returns a list of stored orgs which exist in watchtower.
ListOrgs(ctx context.Context, in *ListOrgsRequest, opts ...grpc.CallOption) (*ListOrgsResponse, error)
// Authenticate validates credentials provided and returns an auth token.
Authenticate(ctx context.Context, in *AuthenticateRequest, opts ...grpc.CallOption) (*AuthenticateResponse, error)
// Logout terminates a user's current session.
Deauthenticate(ctx context.Context, in *DeauthenticateRequest, opts ...grpc.CallOption) (*DeauthenticateResponse, error)
}
type orgServiceClient struct {
@@ -840,24 +441,6 @@ func (c *orgServiceClient) ListOrgs(ctx context.Context, in *ListOrgsRequest, op
return out, nil
}
func (c *orgServiceClient) Authenticate(ctx context.Context, in *AuthenticateRequest, opts ...grpc.CallOption) (*AuthenticateResponse, error) {
out := new(AuthenticateResponse)
err := c.cc.Invoke(ctx, "/controller.api.services.v1.OrgService/Authenticate", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *orgServiceClient) Deauthenticate(ctx context.Context, in *DeauthenticateRequest, opts ...grpc.CallOption) (*DeauthenticateResponse, error) {
out := new(DeauthenticateResponse)
err := c.cc.Invoke(ctx, "/controller.api.services.v1.OrgService/Deauthenticate", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// OrgServiceServer is the server API for OrgService service.
type OrgServiceServer interface {
// GetOrg returns a stored Org if present. The provided request
@@ -866,10 +449,6 @@ type OrgServiceServer interface {
GetOrg(context.Context, *GetOrgRequest) (*GetOrgResponse, error)
// ListOrgs returns a list of stored orgs which exist in watchtower.
ListOrgs(context.Context, *ListOrgsRequest) (*ListOrgsResponse, error)
// Authenticate validates credentials provided and returns an auth token.
Authenticate(context.Context, *AuthenticateRequest) (*AuthenticateResponse, error)
// Logout terminates a user's current session.
Deauthenticate(context.Context, *DeauthenticateRequest) (*DeauthenticateResponse, error)
}
// UnimplementedOrgServiceServer can be embedded to have forward compatible implementations.
@@ -882,12 +461,6 @@ func (*UnimplementedOrgServiceServer) GetOrg(context.Context, *GetOrgRequest) (*
func (*UnimplementedOrgServiceServer) ListOrgs(context.Context, *ListOrgsRequest) (*ListOrgsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListOrgs not implemented")
}
func (*UnimplementedOrgServiceServer) Authenticate(context.Context, *AuthenticateRequest) (*AuthenticateResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Authenticate not implemented")
}
func (*UnimplementedOrgServiceServer) Deauthenticate(context.Context, *DeauthenticateRequest) (*DeauthenticateResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Deauthenticate not implemented")
}
func RegisterOrgServiceServer(s *grpc.Server, srv OrgServiceServer) {
s.RegisterService(&_OrgService_serviceDesc, srv)
@@ -929,42 +502,6 @@ func _OrgService_ListOrgs_Handler(srv interface{}, ctx context.Context, dec func
return interceptor(ctx, in, info, handler)
}
func _OrgService_Authenticate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(AuthenticateRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(OrgServiceServer).Authenticate(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/controller.api.services.v1.OrgService/Authenticate",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(OrgServiceServer).Authenticate(ctx, req.(*AuthenticateRequest))
}
return interceptor(ctx, in, info, handler)
}
func _OrgService_Deauthenticate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DeauthenticateRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(OrgServiceServer).Deauthenticate(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/controller.api.services.v1.OrgService/Deauthenticate",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(OrgServiceServer).Deauthenticate(ctx, req.(*DeauthenticateRequest))
}
return interceptor(ctx, in, info, handler)
}
var _OrgService_serviceDesc = grpc.ServiceDesc{
ServiceName: "controller.api.services.v1.OrgService",
HandlerType: (*OrgServiceServer)(nil),
@@ -977,14 +514,6 @@ var _OrgService_serviceDesc = grpc.ServiceDesc{
MethodName: "ListOrgs",
Handler: _OrgService_ListOrgs_Handler,
},
{
MethodName: "Authenticate",
Handler: _OrgService_Authenticate_Handler,
},
{
MethodName: "Deauthenticate",
Handler: _OrgService_Deauthenticate_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "controller/api/services/v1/org_service.proto",
@@ -139,130 +139,6 @@ func local_request_OrgService_ListOrgs_0(ctx context.Context, marshaler runtime.
}
func request_OrgService_Authenticate_0(ctx context.Context, marshaler runtime.Marshaler, client OrgServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq AuthenticateRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["org_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "org_id")
}
protoReq.OrgId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err)
}
msg, err := client.Authenticate(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_OrgService_Authenticate_0(ctx context.Context, marshaler runtime.Marshaler, server OrgServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq AuthenticateRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["org_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "org_id")
}
protoReq.OrgId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err)
}
msg, err := server.Authenticate(ctx, &protoReq)
return msg, metadata, err
}
func request_OrgService_Deauthenticate_0(ctx context.Context, marshaler runtime.Marshaler, client OrgServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq DeauthenticateRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["org_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "org_id")
}
protoReq.OrgId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err)
}
msg, err := client.Deauthenticate(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_OrgService_Deauthenticate_0(ctx context.Context, marshaler runtime.Marshaler, server OrgServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq DeauthenticateRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["org_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "org_id")
}
protoReq.OrgId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err)
}
msg, err := server.Deauthenticate(ctx, &protoReq)
return msg, metadata, err
}
// RegisterOrgServiceHandlerServer registers the http handlers for service OrgService to "mux".
// UnaryRPC :call OrgServiceServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
@@ -308,46 +184,6 @@ func RegisterOrgServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux,
})
mux.Handle("POST", pattern_OrgService_Authenticate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_OrgService_Authenticate_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_OrgService_Authenticate_0(ctx, mux, outboundMarshaler, w, req, response_OrgService_Authenticate_0{resp}, mux.GetForwardResponseOptions()...)
})
mux.Handle("POST", pattern_OrgService_Deauthenticate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_OrgService_Deauthenticate_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_OrgService_Deauthenticate_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
@@ -429,46 +265,6 @@ func RegisterOrgServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux,
})
mux.Handle("POST", pattern_OrgService_Authenticate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_OrgService_Authenticate_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_OrgService_Authenticate_0(ctx, mux, outboundMarshaler, w, req, response_OrgService_Authenticate_0{resp}, mux.GetForwardResponseOptions()...)
})
mux.Handle("POST", pattern_OrgService_Deauthenticate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_OrgService_Deauthenticate_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_OrgService_Deauthenticate_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
@@ -481,31 +277,14 @@ func (m response_OrgService_GetOrg_0) XXX_ResponseBody() interface{} {
return response.Item
}
type response_OrgService_Authenticate_0 struct {
proto.Message
}
func (m response_OrgService_Authenticate_0) XXX_ResponseBody() interface{} {
response := m.Message.(*AuthenticateResponse)
return response.Item
}
var (
pattern_OrgService_GetOrg_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "orgs", "id"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_OrgService_ListOrgs_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "orgs"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_OrgService_Authenticate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "orgs", "org_id"}, "authenticate", runtime.AssumeColonVerbOpt(true)))
pattern_OrgService_Deauthenticate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "orgs", "org_id"}, "deauthenticate", runtime.AssumeColonVerbOpt(true)))
)
var (
forward_OrgService_GetOrg_0 = runtime.ForwardResponseMessage
forward_OrgService_ListOrgs_0 = runtime.ForwardResponseMessage
forward_OrgService_Authenticate_0 = runtime.ForwardResponseMessage
forward_OrgService_Deauthenticate_0 = runtime.ForwardResponseMessage
)
@@ -627,9 +627,8 @@ type AddRolePrincipalsRequest struct {
RoleId string `protobuf:"bytes,3,opt,name=role_id,json=roleId,proto3" json:"role_id,omitempty"`
// The version ensures the role hasn't changed since it was last retrieved and if
// it has the request will fail.
Version *wrappers.UInt32Value `protobuf:"bytes,4,opt,name=version,proto3" json:"version,omitempty"`
UserIds []string `protobuf:"bytes,5,rep,name=user_ids,proto3" json:"user_ids,omitempty"`
GroupIds []string `protobuf:"bytes,6,rep,name=group_ids,proto3" json:"group_ids,omitempty"`
Version *wrappers.UInt32Value `protobuf:"bytes,4,opt,name=version,proto3" json:"version,omitempty"`
PrincipalIds []string `protobuf:"bytes,5,rep,name=principal_ids,proto3" json:"principal_ids,omitempty"`
}
func (x *AddRolePrincipalsRequest) Reset() {
@@ -692,16 +691,9 @@ func (x *AddRolePrincipalsRequest) GetVersion() *wrappers.UInt32Value {
return nil
}
func (x *AddRolePrincipalsRequest) GetUserIds() []string {
func (x *AddRolePrincipalsRequest) GetPrincipalIds() []string {
if x != nil {
return x.UserIds
}
return nil
}
func (x *AddRolePrincipalsRequest) GetGroupIds() []string {
if x != nil {
return x.GroupIds
return x.PrincipalIds
}
return nil
}
@@ -763,9 +755,8 @@ type SetRolePrincipalsRequest struct {
RoleId string `protobuf:"bytes,3,opt,name=role_id,json=roleId,proto3" json:"role_id,omitempty"`
// The version ensures the role hasn't changed since it was last retrieved and if
// it has the request will fail.
Version *wrappers.UInt32Value `protobuf:"bytes,4,opt,name=version,proto3" json:"version,omitempty"`
UserIds []string `protobuf:"bytes,5,rep,name=user_ids,proto3" json:"user_ids,omitempty"`
GroupIds []string `protobuf:"bytes,6,rep,name=group_ids,proto3" json:"group_ids,omitempty"`
Version *wrappers.UInt32Value `protobuf:"bytes,4,opt,name=version,proto3" json:"version,omitempty"`
PrincipalIds []string `protobuf:"bytes,5,rep,name=principal_ids,proto3" json:"principal_ids,omitempty"`
}
func (x *SetRolePrincipalsRequest) Reset() {
@@ -828,16 +819,9 @@ func (x *SetRolePrincipalsRequest) GetVersion() *wrappers.UInt32Value {
return nil
}
func (x *SetRolePrincipalsRequest) GetUserIds() []string {
func (x *SetRolePrincipalsRequest) GetPrincipalIds() []string {
if x != nil {
return x.UserIds
}
return nil
}
func (x *SetRolePrincipalsRequest) GetGroupIds() []string {
if x != nil {
return x.GroupIds
return x.PrincipalIds
}
return nil
}
@@ -899,9 +883,8 @@ type RemoveRolePrincipalsRequest struct {
RoleId string `protobuf:"bytes,3,opt,name=role_id,json=roleId,proto3" json:"role_id,omitempty"`
// The version ensures the role hasn't changed since it was last retrieved and if
// it has the request will fail.
Version *wrappers.UInt32Value `protobuf:"bytes,4,opt,name=version,proto3" json:"version,omitempty"`
UserIds []string `protobuf:"bytes,5,rep,name=user_ids,proto3" json:"user_ids,omitempty"`
GroupIds []string `protobuf:"bytes,6,rep,name=group_ids,proto3" json:"group_ids,omitempty"`
Version *wrappers.UInt32Value `protobuf:"bytes,4,opt,name=version,proto3" json:"version,omitempty"`
PrincipalIds []string `protobuf:"bytes,5,rep,name=principal_ids,proto3" json:"principal_ids,omitempty"`
}
func (x *RemoveRolePrincipalsRequest) Reset() {
@@ -964,16 +947,9 @@ func (x *RemoveRolePrincipalsRequest) GetVersion() *wrappers.UInt32Value {
return nil
}
func (x *RemoveRolePrincipalsRequest) GetUserIds() []string {
func (x *RemoveRolePrincipalsRequest) GetPrincipalIds() []string {
if x != nil {
return x.UserIds
}
return nil
}
func (x *RemoveRolePrincipalsRequest) GetGroupIds() []string {
if x != nil {
return x.GroupIds
return x.PrincipalIds
}
return nil
}
@@ -1493,7 +1469,7 @@ var file_controller_api_services_v1_role_service_proto_rawDesc = []byte{
0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x2e, 0x0a, 0x12, 0x44, 0x65, 0x6c, 0x65, 0x74,
0x65, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a,
0x07, 0x65, 0x78, 0x69, 0x73, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07,
0x65, 0x78, 0x69, 0x73, 0x74, 0x65, 0x64, 0x22, 0xdb, 0x01, 0x0a, 0x18, 0x41, 0x64, 0x64, 0x52,
0x65, 0x78, 0x69, 0x73, 0x74, 0x65, 0x64, 0x22, 0xc7, 0x01, 0x0a, 0x18, 0x41, 0x64, 0x64, 0x52,
0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6f, 0x72, 0x67, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x70,
@@ -1503,311 +1479,307 @@ var file_controller_api_services_v1_role_service_proto_rawDesc = []byte{
0x65, 0x49, 0x64, 0x12, 0x36, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c,
0x75, 0x65, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x75,
0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x75,
0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x67, 0x72, 0x6f, 0x75, 0x70,
0x5f, 0x69, 0x64, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x67, 0x72, 0x6f, 0x75,
0x70, 0x5f, 0x69, 0x64, 0x73, 0x22, 0x58, 0x0a, 0x19, 0x41, 0x64, 0x64, 0x52, 0x6f, 0x6c, 0x65,
0x75, 0x65, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x0d, 0x70,
0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x05, 0x20, 0x03,
0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x5f, 0x69, 0x64,
0x73, 0x22, 0x58, 0x0a, 0x19, 0x41, 0x64, 0x64, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e,
0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b,
0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x63,
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65,
0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31,
0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0xc7, 0x01, 0x0a, 0x18,
0x53, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c,
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x6f, 0x72, 0x67, 0x5f,
0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6f, 0x72, 0x67, 0x49, 0x64, 0x12,
0x1d, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20,
0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x12, 0x17,
0x0a, 0x07, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
0x06, 0x72, 0x6f, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x36, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69,
0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33,
0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12,
0x24, 0x0a, 0x0d, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x73,
0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61,
0x6c, 0x5f, 0x69, 0x64, 0x73, 0x22, 0x58, 0x0a, 0x19, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65,
0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x12, 0x3b, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70,
0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x72, 0x6f, 0x6c, 0x65,
0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22,
0xdb, 0x01, 0x0a, 0x18, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63,
0x69, 0x70, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06,
0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6f, 0x72,
0x67, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69,
0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74,
0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20,
0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x36, 0x0a, 0x07, 0x76,
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67,
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55,
0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73,
0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18,
0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x12,
0x1c, 0x0a, 0x09, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x06, 0x20, 0x03,
0x28, 0x09, 0x52, 0x09, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x73, 0x22, 0x58, 0x0a,
0x19, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61,
0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x04, 0x69, 0x74,
0xca, 0x01, 0x0a, 0x1b, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72,
0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
0x15, 0x0a, 0x06, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x05, 0x6f, 0x72, 0x67, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63,
0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x6a,
0x65, 0x63, 0x74, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64,
0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x36,
0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x07, 0x76,
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x0d, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69,
0x70, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x70,
0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x73, 0x22, 0x5b, 0x0a, 0x1c,
0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69,
0x70, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x04,
0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x63, 0x6f, 0x6e,
0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f,
0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52,
0x6f, 0x6c, 0x65, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0xb5, 0x01, 0x0a, 0x14, 0x41, 0x64,
0x64, 0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x05, 0x6f, 0x72, 0x67, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x72, 0x6f,
0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70,
0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6c, 0x65,
0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6c, 0x65, 0x49,
0x64, 0x12, 0x36, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65,
0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x67, 0x72, 0x61,
0x6e, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x67, 0x72, 0x61, 0x6e, 0x74,
0x73, 0x22, 0x54, 0x0a, 0x15, 0x41, 0x64, 0x64, 0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e,
0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x04, 0x69, 0x74,
0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72,
0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72,
0x63, 0x65, 0x73, 0x2e, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6c,
0x65, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0xde, 0x01, 0x0a, 0x1b, 0x52, 0x65, 0x6d, 0x6f,
0x76, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x6f, 0x72, 0x67, 0x5f, 0x69,
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6f, 0x72, 0x67, 0x49, 0x64, 0x12, 0x1d,
0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x12, 0x17, 0x0a,
0x07, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
0x72, 0x6f, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x36, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32,
0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1a,
0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09,
0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x67, 0x72,
0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x67,
0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x73, 0x22, 0x5b, 0x0a, 0x1c, 0x52, 0x65, 0x6d, 0x6f,
0x76, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73,
0x65, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0xb5, 0x01, 0x0a, 0x14, 0x53, 0x65, 0x74, 0x52,
0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x12, 0x15, 0x0a, 0x06, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x52, 0x05, 0x6f, 0x72, 0x67, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x6a, 0x65,
0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x72, 0x6f,
0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69,
0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6c, 0x65, 0x49, 0x64, 0x12,
0x36, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x07,
0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x67, 0x72, 0x61, 0x6e, 0x74,
0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x22,
0x54, 0x0a, 0x15, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
0x73, 0x2e, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x52,
0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0xb5, 0x01, 0x0a, 0x14, 0x41, 0x64, 0x64, 0x52, 0x6f, 0x6c,
0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15,
0x0a, 0x06, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05,
0x6f, 0x72, 0x67, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74,
0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x6a, 0x65,
0x63, 0x74, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18,
0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x36, 0x0a,
0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c,
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x07, 0x76, 0x65,
0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x18,
0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x22, 0x54, 0x0a,
0x15, 0x41, 0x64, 0x64, 0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65,
0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e,
0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x04, 0x69,
0x74, 0x65, 0x6d, 0x22, 0xb5, 0x01, 0x0a, 0x14, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x47,
0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06,
0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6f, 0x72,
0x67, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69,
0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74,
0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20,
0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x36, 0x0a, 0x07, 0x76,
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67,
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55,
0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73,
0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x18, 0x05, 0x20,
0x03, 0x28, 0x09, 0x52, 0x06, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x22, 0x54, 0x0a, 0x15, 0x53,
0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e,
0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x72, 0x6f,
0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x04, 0x69, 0x74, 0x65,
0x6d, 0x22, 0xb8, 0x01, 0x0a, 0x17, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x6f, 0x6c, 0x65,
0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a,
0x06, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6f,
0x72, 0x67, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f,
0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63,
0x74, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03,
0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x36, 0x0a, 0x07,
0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e,
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x07, 0x76, 0x65, 0x72,
0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x18, 0x05,
0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x22, 0x57, 0x0a, 0x18,
0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
0x73, 0x2e, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x52,
0x04, 0x69, 0x74, 0x65, 0x6d, 0x32, 0xe4, 0x18, 0x0a, 0x0b, 0x52, 0x6f, 0x6c, 0x65, 0x53, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xe1, 0x01, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6c,
0x65, 0x12, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61,
0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47,
0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e,
0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73,
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f,
0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x7d, 0x82, 0xd3, 0xe4, 0x93,
0x02, 0x60, 0x12, 0x1c, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72,
0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d,
0x5a, 0x3a, 0x12, 0x32, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72,
0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x7b,
0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65,
0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74,
0x65, 0x6d, 0x92, 0x41, 0x14, 0x12, 0x12, 0x47, 0x65, 0x74, 0x73, 0x20, 0x61, 0x20, 0x73, 0x69,
0x6e, 0x67, 0x6c, 0x65, 0x20, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0xce, 0x01, 0x0a, 0x09, 0x4c, 0x69,
0x73, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x12, 0x2c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0xb8, 0x01, 0x0a, 0x17, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65,
0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x12, 0x15, 0x0a, 0x06, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x05, 0x6f, 0x72, 0x67, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x6a,
0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x72,
0x6f, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6c, 0x65, 0x5f,
0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6c, 0x65, 0x49, 0x64,
0x12, 0x36, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52,
0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x67, 0x72, 0x61, 0x6e,
0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73,
0x22, 0x57, 0x0a, 0x18, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72,
0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x04,
0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x63, 0x6f, 0x6e,
0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f,
0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52,
0x6f, 0x6c, 0x65, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x32, 0xe4, 0x18, 0x0a, 0x0b, 0x52, 0x6f,
0x6c, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xe1, 0x01, 0x0a, 0x07, 0x47, 0x65,
0x74, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e,
0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x64, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x4a, 0x12, 0x17, 0x2f, 0x76,
0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f,
0x72, 0x6f, 0x6c, 0x65, 0x73, 0x5a, 0x2f, 0x12, 0x2d, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67,
0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x70, 0x72, 0x6f, 0x6a, 0x65,
0x63, 0x74, 0x73, 0x2f, 0x7b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x7d,
0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x92, 0x41, 0x11, 0x12, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x73,
0x20, 0x61, 0x6c, 0x6c, 0x20, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x12, 0xf0, 0x01, 0x0a, 0x0a, 0x43,
0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74,
0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69,
0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6c,
0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72,
0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6c, 0x65,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x82, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02,
0x62, 0x22, 0x17, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67,
0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d,
0x5a, 0x3b, 0x22, 0x2d, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72,
0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x7b,
0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65,
0x73, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69,
0x74, 0x65, 0x6d, 0x92, 0x41, 0x17, 0x12, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x73, 0x20,
0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0xf3, 0x01,
0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x2d, 0x2e, 0x63,
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x6f,
0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72,
0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52,
0x6f, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x85, 0x01, 0x82, 0xd3,
0xe4, 0x93, 0x02, 0x6c, 0x32, 0x1c, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b,
0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x69,
0x64, 0x7d, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x5a, 0x40, 0x32, 0x32, 0x2f, 0x76, 0x31, 0x2f,
0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x70, 0x72,
0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x7b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f,
0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x04,
0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d,
0x92, 0x41, 0x10, 0x12, 0x0e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x20, 0x61, 0x20, 0x52,
0x6f, 0x6c, 0x65, 0x12, 0xda, 0x01, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f,
0x6c, 0x65, 0x12, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e,
0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e,
0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61,
0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44,
0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x22, 0x6d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x54, 0x2a, 0x1c, 0x2f, 0x76, 0x31, 0x2f, 0x6f,
0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c,
0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x5a, 0x34, 0x2a, 0x32, 0x2f, 0x76, 0x31, 0x2f, 0x6f,
0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x70, 0x72, 0x6f,
0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x7b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69,
0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x92, 0x41, 0x10,
0x12, 0x0e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x73, 0x20, 0x61, 0x20, 0x52, 0x6f, 0x6c, 0x65,
0x12, 0xbf, 0x02, 0x0a, 0x11, 0x41, 0x64, 0x64, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e,
0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x12, 0x34, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73,
0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63,
0x69, 0x70, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63,
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x52, 0x6f, 0x6c,
0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x22, 0xbc, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x8e, 0x01, 0x22, 0x30, 0x2f,
0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d,
0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x7d,
0x3a, 0x61, 0x64, 0x64, 0x2d, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x3a,
0x01, 0x2a, 0x5a, 0x51, 0x22, 0x46, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b,
0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73,
0x2f, 0x7b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f,
0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x3a, 0x61, 0x64,
0x64, 0x2d, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x3a, 0x01, 0x2a, 0x62,
0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x24, 0x12, 0x22,
0x41, 0x64, 0x64, 0x73, 0x20, 0x55, 0x73, 0x65, 0x72, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x2f, 0x6f,
0x72, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x52, 0x6f,
0x6c, 0x65, 0x12, 0xfe, 0x02, 0x0a, 0x11, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72,
0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x12, 0x34, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72,
0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69,
0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35,
0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e,
0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x52,
0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xfb, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x8e, 0x01, 0x22,
0x30, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69,
0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69,
0x64, 0x7d, 0x3a, 0x73, 0x65, 0x74, 0x2d, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c,
0x73, 0x3a, 0x01, 0x2a, 0x5a, 0x51, 0x22, 0x46, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73,
0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61,
0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47,
0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x7d,
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x60, 0x12, 0x1c, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73,
0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f,
0x7b, 0x69, 0x64, 0x7d, 0x5a, 0x3a, 0x12, 0x32, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73,
0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63,
0x74, 0x73, 0x2f, 0x7b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x7d, 0x2f,
0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x3a,
0x73, 0x65, 0x74, 0x2d, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x3a, 0x01,
0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x63,
0x12, 0x61, 0x53, 0x65, 0x74, 0x20, 0x55, 0x73, 0x65, 0x72, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x2f,
0x6f, 0x72, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x52,
0x6f, 0x6c, 0x65, 0x2c, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e,
0x79, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x20, 0x74, 0x68, 0x61,
0x74, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66,
0x69, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x2e, 0x12, 0xe2, 0x02, 0x0a, 0x14, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x6f,
0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x12, 0x37, 0x2e, 0x63,
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65,
0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e,
0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69,
0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
0xd6, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x94, 0x01, 0x22, 0x33, 0x2f, 0x76, 0x31, 0x2f, 0x6f,
0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c,
0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x3a, 0x72, 0x65, 0x6d,
0x6f, 0x76, 0x65, 0x2d, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x3a, 0x01,
0x2a, 0x5a, 0x54, 0x22, 0x49, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f,
0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f,
0x7b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c,
0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x3a, 0x72, 0x65, 0x6d,
0x6f, 0x76, 0x65, 0x2d, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x3a, 0x01,
0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x38,
0x12, 0x36, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x70,
0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x55, 0x73, 0x65, 0x72, 0x73, 0x20, 0x61, 0x6e,
0x64, 0x2f, 0x6f, 0x72, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d,
0x20, 0x61, 0x20, 0x52, 0x6f, 0x6c, 0x65, 0x2e, 0x12, 0x9e, 0x02, 0x0a, 0x0d, 0x41, 0x64, 0x64,
0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x30, 0x2e, 0x63, 0x6f, 0x6e,
0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76,
0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x52, 0x6f, 0x6c, 0x65, 0x47,
0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x63,
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x52, 0x6f, 0x6c,
0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
0xa7, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x86, 0x01, 0x22, 0x2c, 0x2f, 0x76, 0x31, 0x2f, 0x6f,
0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c,
0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x3a, 0x61, 0x64, 0x64,
0x2d, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x3a, 0x01, 0x2a, 0x5a, 0x4d, 0x22, 0x42, 0x2f, 0x76,
0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f,
0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x7b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63,
0x74, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x6c,
0x65, 0x5f, 0x69, 0x64, 0x7d, 0x3a, 0x61, 0x64, 0x64, 0x2d, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73,
0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92,
0x41, 0x17, 0x12, 0x15, 0x41, 0x64, 0x64, 0x73, 0x20, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x20,
0x74, 0x6f, 0x20, 0x61, 0x20, 0x72, 0x6f, 0x6c, 0x65, 0x12, 0xda, 0x02, 0x0a, 0x0d, 0x53, 0x65,
0x74, 0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x30, 0x2e, 0x63, 0x6f,
0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d,
0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x14, 0x12, 0x12, 0x47, 0x65, 0x74, 0x73, 0x20,
0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0xce, 0x01,
0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x12, 0x2c, 0x2e, 0x63, 0x6f,
0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72,
0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65,
0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e,
0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6c,
0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74,
0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69,
0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x73,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x64, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x4a,
0x12, 0x17, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f,
0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x5a, 0x2f, 0x12, 0x2d, 0x2f, 0x76, 0x31,
0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x70,
0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x7b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74,
0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x92, 0x41, 0x11, 0x12, 0x0f, 0x4c,
0x69, 0x73, 0x74, 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x12, 0xf0,
0x01, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x2d, 0x2e,
0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73,
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x52, 0x6f,
0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x22, 0xe3, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x86, 0x01, 0x22, 0x2c, 0x2f, 0x76, 0x31, 0x2f,
0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f,
0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x3a, 0x73, 0x65,
0x74, 0x2d, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x3a, 0x01, 0x2a, 0x5a, 0x4d, 0x22, 0x42, 0x2f,
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74,
0x65, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63,
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65,
0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x82, 0x01, 0x82,
0xd3, 0xe4, 0x93, 0x02, 0x62, 0x22, 0x17, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f,
0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x3a, 0x04,
0x69, 0x74, 0x65, 0x6d, 0x5a, 0x3b, 0x22, 0x2d, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73,
0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63,
0x74, 0x73, 0x2f, 0x7b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x7d, 0x2f,
0x72, 0x6f, 0x6c, 0x65, 0x73, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65,
0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x17, 0x12, 0x15, 0x43, 0x72, 0x65, 0x61,
0x74, 0x65, 0x73, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x52, 0x6f, 0x6c,
0x65, 0x12, 0xf3, 0x01, 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6c, 0x65,
0x12, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70,
0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70,
0x64, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69,
0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64,
0x61, 0x74, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
0x85, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x6c, 0x32, 0x1c, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72,
0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65,
0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x5a, 0x40, 0x32, 0x32,
0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64,
0x7d, 0x2f, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x7b, 0x70, 0x72, 0x6f, 0x6a,
0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x69,
0x64, 0x7d, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04,
0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x10, 0x12, 0x0e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73,
0x20, 0x61, 0x20, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0xda, 0x01, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65,
0x74, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73,
0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e,
0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x6d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x54, 0x2a, 0x1c, 0x2f,
0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d,
0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x5a, 0x34, 0x2a, 0x32, 0x2f,
0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d,
0x2f, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x7b, 0x70, 0x72, 0x6f, 0x6a, 0x65,
0x63, 0x74, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f,
0x6c, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x3a, 0x73, 0x65, 0x74, 0x2d, 0x67, 0x72, 0x61, 0x6e, 0x74,
0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d,
0x92, 0x41, 0x53, 0x12, 0x51, 0x53, 0x65, 0x74, 0x20, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x20,
0x66, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x72, 0x6f, 0x6c, 0x65, 0x2c, 0x20, 0x72, 0x65, 0x6d, 0x6f,
0x76, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x20,
0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x70, 0x65,
0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x12, 0xb3, 0x02, 0x0a, 0x10, 0x52, 0x65, 0x6d, 0x6f, 0x76,
0x65, 0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x33, 0x2e, 0x63, 0x6f,
0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72,
0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52,
0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x34, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70,
0x63, 0x74, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64,
0x7d, 0x92, 0x41, 0x10, 0x12, 0x0e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x73, 0x20, 0x61, 0x20,
0x52, 0x6f, 0x6c, 0x65, 0x12, 0xbf, 0x02, 0x0a, 0x11, 0x41, 0x64, 0x64, 0x52, 0x6f, 0x6c, 0x65,
0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x12, 0x34, 0x2e, 0x63, 0x6f, 0x6e,
0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76,
0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x52, 0x6f, 0x6c, 0x65, 0x50,
0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x35, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70,
0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64,
0x64, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xbc, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x8e,
0x01, 0x22, 0x30, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67,
0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x6c, 0x65,
0x5f, 0x69, 0x64, 0x7d, 0x3a, 0x61, 0x64, 0x64, 0x2d, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70,
0x61, 0x6c, 0x73, 0x3a, 0x01, 0x2a, 0x5a, 0x51, 0x22, 0x46, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72,
0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x70, 0x72, 0x6f, 0x6a,
0x65, 0x63, 0x74, 0x73, 0x2f, 0x7b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64,
0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64,
0x7d, 0x3a, 0x61, 0x64, 0x64, 0x2d, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73,
0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92,
0x41, 0x24, 0x12, 0x22, 0x41, 0x64, 0x64, 0x73, 0x20, 0x55, 0x73, 0x65, 0x72, 0x73, 0x20, 0x61,
0x6e, 0x64, 0x2f, 0x6f, 0x72, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x20, 0x74, 0x6f, 0x20,
0x61, 0x20, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0xfe, 0x02, 0x0a, 0x11, 0x53, 0x65, 0x74, 0x52, 0x6f,
0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x12, 0x34, 0x2e, 0x63,
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6c,
0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e,
0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e,
0x53, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c,
0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xfb, 0x01, 0x82, 0xd3, 0xe4, 0x93,
0x02, 0x8e, 0x01, 0x22, 0x30, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f,
0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f,
0x6c, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x3a, 0x73, 0x65, 0x74, 0x2d, 0x70, 0x72, 0x69, 0x6e, 0x63,
0x69, 0x70, 0x61, 0x6c, 0x73, 0x3a, 0x01, 0x2a, 0x5a, 0x51, 0x22, 0x46, 0x2f, 0x76, 0x31, 0x2f,
0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x70, 0x72,
0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x7b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f,
0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x6c, 0x65, 0x5f,
0x69, 0x64, 0x7d, 0x3a, 0x73, 0x65, 0x74, 0x2d, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61,
0x6c, 0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65,
0x6d, 0x92, 0x41, 0x63, 0x12, 0x61, 0x53, 0x65, 0x74, 0x20, 0x55, 0x73, 0x65, 0x72, 0x73, 0x20,
0x61, 0x6e, 0x64, 0x2f, 0x6f, 0x72, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x20, 0x74, 0x6f,
0x20, 0x61, 0x20, 0x52, 0x6f, 0x6c, 0x65, 0x2c, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x69, 0x6e,
0x67, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73,
0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x70,
0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x12, 0xe2, 0x02, 0x0a, 0x14, 0x52, 0x65, 0x6d, 0x6f,
0x76, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73,
0x12, 0x37, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70,
0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65,
0x6d, 0x6f, 0x76, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xb3, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x8c, 0x01,
0x22, 0x2f, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f,
0x6d, 0x6f, 0x76, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61,
0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x63, 0x6f, 0x6e, 0x74,
0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69,
0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x6f, 0x6c,
0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x22, 0xd6, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x94, 0x01, 0x22, 0x33, 0x2f,
0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d,
0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x7d,
0x3a, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x2d, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61,
0x6c, 0x73, 0x3a, 0x01, 0x2a, 0x5a, 0x54, 0x22, 0x49, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67,
0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x70, 0x72, 0x6f, 0x6a, 0x65,
0x63, 0x74, 0x73, 0x2f, 0x7b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x7d,
0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x7d,
0x3a, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x2d, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61,
0x6c, 0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65,
0x6d, 0x92, 0x41, 0x38, 0x12, 0x36, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x73, 0x20, 0x74, 0x68,
0x65, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x55, 0x73, 0x65, 0x72,
0x73, 0x20, 0x61, 0x6e, 0x64, 0x2f, 0x6f, 0x72, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x20,
0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61, 0x20, 0x52, 0x6f, 0x6c, 0x65, 0x2e, 0x12, 0x9e, 0x02, 0x0a,
0x0d, 0x41, 0x64, 0x64, 0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x30,
0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e,
0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x52,
0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70,
0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64,
0x64, 0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x22, 0xa7, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x86, 0x01, 0x22, 0x2c, 0x2f,
0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d,
0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x7d,
0x3a, 0x61, 0x64, 0x64, 0x2d, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x3a, 0x01, 0x2a, 0x5a, 0x4d,
0x22, 0x42, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f,
0x69, 0x64, 0x7d, 0x2f, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x7b, 0x70, 0x72,
0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f,
0x7b, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x3a, 0x61, 0x64, 0x64, 0x2d, 0x67, 0x72,
0x61, 0x6e, 0x74, 0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69,
0x74, 0x65, 0x6d, 0x92, 0x41, 0x17, 0x12, 0x15, 0x41, 0x64, 0x64, 0x73, 0x20, 0x67, 0x72, 0x61,
0x6e, 0x74, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x72, 0x6f, 0x6c, 0x65, 0x12, 0xda, 0x02,
0x0a, 0x0d, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12,
0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69,
0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74,
0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61,
0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53,
0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x22, 0xe3, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x86, 0x01, 0x22, 0x2c,
0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64,
0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64,
0x7d, 0x3a, 0x73, 0x65, 0x74, 0x2d, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x3a, 0x01, 0x2a, 0x5a,
0x4d, 0x22, 0x42, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67,
0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x7b, 0x70,
0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73,
0x2f, 0x7b, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x3a, 0x73, 0x65, 0x74, 0x2d, 0x67,
0x72, 0x61, 0x6e, 0x74, 0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04,
0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x53, 0x12, 0x51, 0x53, 0x65, 0x74, 0x20, 0x67, 0x72, 0x61,
0x6e, 0x74, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x72, 0x6f, 0x6c, 0x65, 0x2c, 0x20,
0x72, 0x65, 0x6d, 0x6f, 0x76, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x67, 0x72, 0x61,
0x6e, 0x74, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6e, 0x6f, 0x74,
0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x12, 0xb3, 0x02, 0x0a, 0x10, 0x52,
0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12,
0x33, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69,
0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d,
0x6f, 0x76, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65,
0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76,
0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x47, 0x72, 0x61, 0x6e,
0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xb3, 0x01, 0x82, 0xd3, 0xe4,
0x93, 0x02, 0x8c, 0x01, 0x22, 0x2f, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b,
0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x72,
0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x3a, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x2d, 0x67,
0x72, 0x61, 0x6e, 0x74, 0x73, 0x3a, 0x01, 0x2a, 0x5a, 0x50, 0x22, 0x45, 0x2f, 0x76, 0x31, 0x2f,
0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x70, 0x72,
0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x7b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f,
0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x6c, 0x65, 0x5f,
0x69, 0x64, 0x7d, 0x3a, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x2d, 0x67, 0x72, 0x61, 0x6e, 0x74,
0x73, 0x3a, 0x01, 0x2a, 0x5a, 0x50, 0x22, 0x45, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73,
0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63,
0x74, 0x73, 0x2f, 0x7b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x7d, 0x2f,
0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x3a,
0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x2d, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x3a, 0x01, 0x2a,
0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x1d, 0x12,
0x1b, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x73, 0x20, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x20,
0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61, 0x20, 0x72, 0x6f, 0x6c, 0x65, 0x2e, 0x42, 0x4f, 0x5a, 0x4d,
0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69,
0x63, 0x6f, 0x72, 0x70, 0x2f, 0x77, 0x61, 0x74, 0x63, 0x68, 0x74, 0x6f, 0x77, 0x65, 0x72, 0x2f,
0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e,
0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76,
0x69, 0x63, 0x65, 0x73, 0x3b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x62, 0x06, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x33,
0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d,
0x92, 0x41, 0x1d, 0x12, 0x1b, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x73, 0x20, 0x67, 0x72, 0x61,
0x6e, 0x74, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61, 0x20, 0x72, 0x6f, 0x6c, 0x65, 0x2e,
0x42, 0x4f, 0x5a, 0x4d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68,
0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x77, 0x61, 0x74, 0x63, 0x68, 0x74, 0x6f,
0x77, 0x65, 0x72, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e,
0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f,
0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x3b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
+33 -3
View File
@@ -3,6 +3,7 @@ package iam
import (
"context"
"fmt"
"strings"
"github.com/hashicorp/watchtower/internal/db"
"github.com/hashicorp/watchtower/internal/oplog"
@@ -12,10 +13,14 @@ import (
// groupIds) to a role (roleId). The role's current db version must match the
// roleVersion or an error will be returned. The list of current PrincipalRoles
// after the adds will be returned on success.
func (r *Repository) AddPrincipalRoles(ctx context.Context, roleId string, roleVersion uint32, userIds, groupIds []string, opt ...Option) ([]PrincipalRole, error) {
func (r *Repository) AddPrincipalRoles(ctx context.Context, roleId string, roleVersion uint32, principalIds []string, opt ...Option) ([]PrincipalRole, error) {
if roleId == "" {
return nil, fmt.Errorf("add principal roles: missing role id: %w", db.ErrInvalidParameter)
}
userIds, groupIds, err := splitPrincipals(principalIds)
if err != nil {
return nil, fmt.Errorf("add principal roles: error parsing principals: %w", err)
}
if len(userIds) == 0 && len(groupIds) == 0 {
return nil, fmt.Errorf("add principal roles: missing either user or groups to add: %w", db.ErrInvalidParameter)
}
@@ -114,7 +119,7 @@ func (r *Repository) AddPrincipalRoles(ctx context.Context, roleId string, roleV
// principals as need to reconcile the existing principals with the principals
// requested. If both userIds and groupIds are empty, the principal roles will
// be cleared.
func (r *Repository) SetPrincipalRoles(ctx context.Context, roleId string, roleVersion uint32, userIds, groupIds []string, opt ...Option) ([]PrincipalRole, int, error) {
func (r *Repository) SetPrincipalRoles(ctx context.Context, roleId string, roleVersion uint32, principalIds []string, opt ...Option) ([]PrincipalRole, int, error) {
if roleId == "" {
return nil, db.NoRowsAffected, fmt.Errorf("set principal roles: missing role id: %w", db.ErrInvalidParameter)
}
@@ -127,6 +132,10 @@ func (r *Repository) SetPrincipalRoles(ctx context.Context, roleId string, roleV
// it's "safe" to do this lookup outside the DoTx transaction because we
// have a roleVersion so the principals can’t change without the version
// changing.
userIds, groupIds, err := splitPrincipals(principalIds)
if err != nil {
return nil, db.NoRowsAffected, fmt.Errorf("set principal roles: error parsing principals: %w", err)
}
toSet, err := r.principalsToSet(ctx, &role, userIds, groupIds)
if err != nil {
return nil, db.NoRowsAffected, fmt.Errorf("set principal roles: unable to determine set: %w", err)
@@ -243,10 +252,14 @@ func (r *Repository) SetPrincipalRoles(ctx context.Context, roleId string, roleV
// DeletePrincipalRoles principals (userIds and/or groupIds) from a role
// (roleId). The role's current db version must match the roleVersion or an
// error will be returned.
func (r *Repository) DeletePrincipalRoles(ctx context.Context, roleId string, roleVersion uint32, userIds, groupIds []string, opt ...Option) (int, error) {
func (r *Repository) DeletePrincipalRoles(ctx context.Context, roleId string, roleVersion uint32, principalIds []string, opt ...Option) (int, error) {
if roleId == "" {
return db.NoRowsAffected, fmt.Errorf("delete principal roles: missing role id: %w", db.ErrInvalidParameter)
}
userIds, groupIds, err := splitPrincipals(principalIds)
if err != nil {
return db.NoRowsAffected, fmt.Errorf("remove principal roles: error parsing principals: %w", err)
}
if len(userIds) == 0 && len(groupIds) == 0 {
return db.NoRowsAffected, fmt.Errorf("delete principal roles: missing either user or groups to delete: %w", db.ErrInvalidParameter)
}
@@ -441,3 +454,20 @@ func (r *Repository) principalsToSet(ctx context.Context, role *Role, userIds, g
return toSet, nil
}
func splitPrincipals(principals []string) ([]string, []string, error) {
var users, groups []string
for _, principal := range principals {
switch {
case strings.HasPrefix(principal, UserPrefix):
users = append(users, principal)
// TODO: This needs to handle all of the kinds of group prefixes (sg_, dg_, etc.)
case strings.HasPrefix(principal, GroupPrefix):
groups = append(groups, principal)
default:
return nil, nil, fmt.Errorf("invalid principal ID %q: %w", principal, db.ErrInvalidParameter)
}
}
return users, groups, nil
}
+13 -9
View File
@@ -132,7 +132,8 @@ func TestRepository_AddPrincipalRoles(t *testing.T) {
groupIds = append(groupIds, g.PublicId)
}
}
got, err := repo.AddPrincipalRoles(context.Background(), roleId, tt.args.roleVersion, userIds, groupIds, tt.args.opt...)
principalIds := append(userIds, groupIds...)
got, err := repo.AddPrincipalRoles(context.Background(), roleId, tt.args.roleVersion, principalIds, tt.args.opt...)
if tt.wantErr {
require.Error(err)
if tt.wantErrIs != nil {
@@ -236,7 +237,7 @@ func TestRepository_ListPrincipalRoles(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
require.NoError(conn.Where("1=1").Delete(allocRole()).Error)
require.NoError(conn.Where("public_id != ?", "r_default").Delete(allocRole()).Error)
role := TestRole(t, conn, tt.createScopeId)
userRoles := make([]string, 0, tt.createCnt)
groupRoles := make([]string, 0, tt.createCnt)
@@ -246,7 +247,8 @@ func TestRepository_ListPrincipalRoles(t *testing.T) {
g := TestGroup(t, conn, tt.createScopeId)
groupRoles = append(groupRoles, g.PublicId)
}
testRoles, err := repo.AddPrincipalRoles(context.Background(), role.PublicId, role.Version, userRoles, groupRoles, tt.args.opt...)
principalIds := append(userRoles, groupRoles...)
testRoles, err := repo.AddPrincipalRoles(context.Background(), role.PublicId, role.Version, principalIds, tt.args.opt...)
require.NoError(err)
assert.Equal(tt.createCnt, len(testRoles))
@@ -406,7 +408,8 @@ func TestRepository_DeletePrincipalRoles(t *testing.T) {
groupIds = append(groupIds, g.PublicId)
}
}
principalRoles, err := repo.AddPrincipalRoles(context.Background(), tt.args.role.PublicId, 1, userIds, groupIds, tt.args.opt...)
principalIds := append(userIds, groupIds...)
principalRoles, err := repo.AddPrincipalRoles(context.Background(), tt.args.role.PublicId, 1, principalIds, tt.args.opt...)
require.NoError(err)
assert.Equal(tt.args.createUserCnt+tt.args.createGroupCnt, len(principalRoles))
@@ -425,7 +428,8 @@ func TestRepository_DeletePrincipalRoles(t *testing.T) {
default:
roleId = tt.args.role.PublicId
}
deletedRows, err := repo.DeletePrincipalRoles(context.Background(), roleId, 2, deleteUserIds, deleteGroupIds, tt.args.opt...)
principalIds = append(deleteUserIds, deleteGroupIds...)
deletedRows, err := repo.DeletePrincipalRoles(context.Background(), roleId, 2, principalIds, tt.args.opt...)
if tt.wantErr {
assert.Error(err)
assert.Equal(0, deletedRows)
@@ -480,7 +484,7 @@ func TestRepository_SetPrincipalRoles(t *testing.T) {
users := createUsersFn()
grps := createGrpsFn()
var err error
_, err = repo.AddPrincipalRoles(context.Background(), role.PublicId, 1, users, grps)
_, err = repo.AddPrincipalRoles(context.Background(), role.PublicId, 1, append(users, grps...))
require.NoError(t, err)
return users, grps
}
@@ -568,8 +572,8 @@ func TestRepository_SetPrincipalRoles(t *testing.T) {
if tt.args.addToOrigGrps {
tt.args.groupIds = append(tt.args.groupIds, origGrps...)
}
got, affectedRows, err := repo.SetPrincipalRoles(context.Background(), tt.args.role.PublicId, tt.args.roleVersion, tt.args.userIds, tt.args.groupIds, tt.args.opt...)
principalIds := append(tt.args.userIds, tt.args.groupIds...)
got, affectedRows, err := repo.SetPrincipalRoles(context.Background(), tt.args.role.PublicId, tt.args.roleVersion, principalIds, tt.args.opt...)
if tt.wantErr {
require.Error(err)
return
@@ -619,7 +623,7 @@ func TestRepository_principalsToSet(t *testing.T) {
users := createUsersFn()
grps := createGrpsFn()
role := TestRole(t, conn, proj.PublicId)
_, err := repo.AddPrincipalRoles(context.Background(), role.PublicId, 1, users, grps)
_, err := repo.AddPrincipalRoles(context.Background(), role.PublicId, 1, append(users, grps...))
require.NoError(t, err)
return role, users, grps
}
+87
View File
@@ -351,3 +351,90 @@ func (r *Repository) ListRoleGrants(ctx context.Context, roleId string, opt ...O
}
return roleGrants, nil
}
func (r *Repository) GrantsForUser(ctx context.Context, userId string, opt ...Option) ([]perms.GrantPair, error) {
if userId == "" {
return nil, fmt.Errorf("get grants for user: missing user id: %w", db.ErrInvalidParameter)
}
const (
anonUser = `where public_id in ($1)`
authUser = `where public_id in ('u_anon', 'u_auth', $1)`
grantsQuery = `
with
users (id) as (
select public_id
from iam_user
%s -- anonUser || authUser
),
user_groups (id) as (
select group_id
from iam_group_member_user,
users
where member_id in (users.id)
),
group_roles (role_id) as (
select role_id
from iam_group_role,
user_groups
where principal_id in (user_groups.id)
),
user_roles (role_id) as (
select role_id
from iam_user_role,
users
where principal_id in (users.id)
),
user_group_roles (role_id) as (
select role_id
from group_roles
union
select role_id
from user_roles
),
roles (role_id, grant_scope_id) as (
select iam_role.public_id,
iam_role.grant_scope_id
from iam_role,
user_group_roles
where public_id in (user_group_roles.role_id)
),
final (role_scope, role_grant) as (
select roles.grant_scope_id,
iam_role_grant.canonical_grant
from roles
inner
join iam_role_grant
on roles.role_id = iam_role_grant.role_id
)
select role_scope as scope_id, role_grant as grant from final;
`
)
var query string
switch userId {
case "u_anon":
query = fmt.Sprintf(grantsQuery, anonUser)
default:
query = fmt.Sprintf(grantsQuery, authUser)
}
var grants []perms.GrantPair
tx, err := r.reader.DB()
if err != nil {
return nil, err
}
rows, err := tx.Query(query, userId)
if err != nil {
return nil, err
}
defer rows.Close()
for rows.Next() {
var g perms.GrantPair
if err := r.reader.ScanRows(rows, &g); err != nil {
return nil, err
}
grants = append(grants, g)
}
return grants, nil
}
+1 -1
View File
@@ -184,7 +184,7 @@ func TestRepository_ListRoleGrants(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
require.NoError(conn.Where("1=1").Delete(allocRole()).Error)
require.NoError(conn.Where("public_id != ?", "r_default").Delete(allocRole()).Error)
role := TestRole(t, conn, tt.createScopeId)
roleGrants := make([]string, 0, tt.createCnt)
for i := 0; i < tt.createCnt; i++ {
+1 -1
View File
@@ -30,7 +30,7 @@ func (r *Repository) CreateScope(ctx context.Context, s *Scope, opt ...Option) (
}
opts := getOpts(opt...)
var publicId string
t := scope.StringToScopeType(s.Type)
t := scope.Map[s.Type]
if opts.withPublicId != "" {
if !strings.HasPrefix(opts.withPublicId, t.Prefix()+"_") {
return nil, fmt.Errorf("create scope: passed-in public ID %q has wrong prefix for type %q which uses prefix %q", opts.withPublicId, t.String(), t.Prefix())
+13 -2
View File
@@ -12,6 +12,13 @@ import (
"github.com/hashicorp/watchtower/internal/types/scope"
)
// GrantPair is simply a struct that can be reference from other code to return
// a set of scopes and grants to parse
type GrantPair struct {
ScopeId string
Grant string
}
// Scope provides an in-memory representation of iam.Scope without the
// underlying storage references or capabilities.
type Scope struct {
@@ -123,7 +130,10 @@ func (g *Grant) unmarshalJSON(data []byte) error {
if !ok {
return fmt.Errorf("unable to interpret %q as string", "type")
}
g.typ = resource.StringToResourceType(typ)
g.typ = resource.Map[typ]
if g.typ == resource.Unknown {
return fmt.Errorf("unknown type specifier %q", typ)
}
}
if rawActions, ok := raw["actions"]; ok {
interfaceActions, ok := rawActions.([]interface{})
@@ -169,7 +179,7 @@ func (g *Grant) unmarshalText(grantString string) error {
case "type":
typeString := strings.ToLower(kv[1])
g.typ = resource.StringToResourceType(typeString)
g.typ = resource.Map[typeString]
if g.typ == resource.Unknown {
return fmt.Errorf("unknown type specifier %q", typeString)
}
@@ -273,6 +283,7 @@ func (g Grant) validateType() error {
resource.HostCatalog,
resource.HostSet,
resource.Host,
resource.Org,
resource.Target:
return nil
}
@@ -7,6 +7,26 @@ option go_package = "github.com/hashicorp/watchtower/internal/gen/controller/api
import "google/protobuf/timestamp.proto";
import "google/protobuf/wrappers.proto";
message Principal {
// The ID of the principal.
// Output only.
string id = 1;
// The type of the principal.
// Output only.
string type = 2;
// The scope ID of the principal.
// Output only.
string scope_id = 3 [json_name="scope_id"];
}
message Grant {
// The user-supplied string.
// Output only.
}
// Role contains all fields related to a Role resource
message Role {
// The ID of the Role
@@ -42,13 +62,15 @@ message Role {
// Output only.
uint32 version = 8;
// The principals that are assigned this role.
// The IDs (only) of principals that are assigned to this role.
// Output only.
repeated string user_ids = 9;
// Output only.
repeated string group_ids = 10;
repeated string principal_ids = 9 [json_name="principal_ids"];
// The grants that this role provides for it's principals.
// The principals that are assigned to this role.
// Output only.
repeated Principal principals = 10;
// The grants that this role provides for its principals.
// Output only.
repeated string grants = 11;
@@ -0,0 +1,63 @@
syntax = "proto3";
package controller.api.services.v1;
option go_package = "github.com/hashicorp/watchtower/internal/gen/controller/api/services;services";
import "protoc-gen-swagger/options/annotations.proto";
import "google/api/annotations.proto";
import "google/protobuf/struct.proto";
import "controller/api/resources/authtokens/v1/authtoken.proto";
service AuthenticationService {
// Authenticate validates credentials provided and returns an auth token.
rpc Authenticate(AuthenticateRequest) returns (AuthenticateResponse) {
option (google.api.http) = {
post: "/v1/orgs/{org_id}/auth-methods/{auth_method_id}:authenticate"
body: "*"
response_body: "item"
};
option (grpc.gateway.protoc_gen_swagger.options.openapiv2_operation) = {
summary: "Authenticate a user to an Org and retrieve an authentication token."
};
}
// Logout terminates a user's current session.
rpc Deauthenticate(DeauthenticateRequest) returns (DeauthenticateResponse) {
option (google.api.http) = {
post: "/v1/orgs/{org_id}:deauthenticate"
};
option (grpc.gateway.protoc_gen_swagger.options.openapiv2_operation) = {
summary: "Deauthenticate an authentication token from an Org."
};
}
}
// The layout of the struct for "credentials" field in AuthenticateRequest. This message isn't
// directly referenced anywhere but is used here to define the expected field names and types.
message PasswordCredentials {
string name = 1;
string password = 2;
}
message AuthenticateRequest {
string org_id = 1;
// The id to the authmethod in the system being used for authentication. The auth method must be in the org
// being logged in to.
string auth_method_id = 2;
// This can be "cookie" or "token". If not provided, "token" will be used. For now only type "token" is returned.
string token_type = 3;
// credentials are the different possible credential names depending on what type of auth method is used.
// For password auth method: should include only "name" and "password".
google.protobuf.Struct credentials = 8;
}
message AuthenticateResponse {
resources.authtokens.v1.AuthToken item = 1;
}
message DeauthenticateRequest {
string org_id = 1;
}
message DeauthenticateResponse {}
@@ -7,7 +7,6 @@ option go_package = "github.com/hashicorp/watchtower/internal/gen/controller/api
import "protoc-gen-swagger/options/annotations.proto";
import "google/api/annotations.proto";
import "controller/api/resources/scopes/v1/org.proto";
import "controller/api/resources/authtokens/v1/authtoken.proto";
service OrgService {
@@ -33,28 +32,6 @@ service OrgService {
summary: "Lists all Orgs"
};
}
// Authenticate validates credentials provided and returns an auth token.
rpc Authenticate(AuthenticateRequest) returns (AuthenticateResponse) {
option (google.api.http) = {
post: "/v1/orgs/{org_id}:authenticate"
body: "*"
response_body: "item"
};
option (grpc.gateway.protoc_gen_swagger.options.openapiv2_operation) = {
summary: "Authenticate a user to an Org and retrieve an authentication token."
};
}
// Logout terminates a user's current session.
rpc Deauthenticate(DeauthenticateRequest) returns (DeauthenticateResponse) {
option (google.api.http) = {
post: "/v1/orgs/{org_id}:deauthenticate"
};
option (grpc.gateway.protoc_gen_swagger.options.openapiv2_operation) = {
summary: "Deauthenticate an authentication token from an Org."
};
}
}
message GetOrgRequest {
@@ -73,28 +50,3 @@ message ListOrgsRequest {
message ListOrgsResponse {
repeated resources.scopes.v1.Org items = 1;
}
message PasswordCredential {
string login_name = 1;
string password = 2;
}
message AuthenticateRequest {
string org_id = 1;
// The id to the authmethod in the system being used for authentication. The auth method must be in the org
// being logged in to.
string auth_method_id = 2;
// This can be "cookie" or "token". If not provided, "token" will be used. For now only type "token" is returned.
string token_type = 3;
PasswordCredential password_credential = 4;
}
message AuthenticateResponse {
resources.authtokens.v1.AuthToken item = 1;
}
message DeauthenticateRequest {
string org_id = 1;
}
message DeauthenticateResponse {}
@@ -296,8 +296,7 @@ message AddRolePrincipalsRequest {
// The version ensures the role hasn't changed since it was last retrieved and if
// it has the request will fail.
google.protobuf.UInt32Value version = 4;
repeated string user_ids = 5 [json_name="user_ids"];
repeated string group_ids = 6 [json_name="group_ids"];
repeated string principal_ids = 5 [json_name="principal_ids"];
}
message AddRolePrincipalsResponse {
@@ -311,8 +310,7 @@ message SetRolePrincipalsRequest {
// The version ensures the role hasn't changed since it was last retrieved and if
// it has the request will fail.
google.protobuf.UInt32Value version = 4;
repeated string user_ids = 5 [json_name="user_ids"];
repeated string group_ids = 6 [json_name="group_ids"];
repeated string principal_ids = 5 [json_name="principal_ids"];
}
message SetRolePrincipalsResponse {
@@ -326,8 +324,7 @@ message RemoveRolePrincipalsRequest {
// The version ensures the role hasn't changed since it was last retrieved and if
// it has the request will fail.
google.protobuf.UInt32Value version = 4;
repeated string user_ids = 5 [json_name="user_ids"];
repeated string group_ids = 6 [json_name="group_ids"];
repeated string principal_ids = 5 [json_name="principal_ids"];
}
message RemoveRolePrincipalsResponse {
+7 -4
View File
@@ -1,14 +1,17 @@
package controller
import (
"context"
"github.com/hashicorp/watchtower/internal/cmd/base"
"github.com/hashicorp/watchtower/internal/cmd/config"
)
type Config struct {
// The base Server object, containing things shared between Controllers and
// Workers
*base.Server
RawConfig *config.Config
BaseContext context.Context
// The underlying configuration, passed in here to avoid duplicating values
// everywhere
RawConfig *config.Config
// If set, authorization checking occurrs but failures are ignored
DisableAuthorizationFailures bool
}
+8 -5
View File
@@ -6,6 +6,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/hashicorp/watchtower/internal/cmd/config"
)
@@ -65,8 +66,9 @@ func TestHandler_CORS(t *testing.T) {
t.Fatal(err)
}
tc := NewTestController(t, &TestControllerOpts{
Config: cfg,
DefaultOrgId: "o_1234567890",
Config: cfg,
DefaultOrgId: "o_1234567890",
DisableAuthorizationFailures: true,
})
defer tc.Shutdown()
@@ -161,12 +163,13 @@ func TestHandler_CORS(t *testing.T) {
t.Run(c.name, func(t *testing.T) {
// Create a client with the right address
client := tc.Client()
client.SetAddr(tc.ApiAddrs()[c.listenerNum-1])
err := client.SetAddr(tc.ApiAddrs()[c.listenerNum-1])
require.NoError(t, err)
client.SetOrg("o_1234567890")
// Create the request
req, err := client.NewRequest(tc.Context(), c.method, "projects", nil)
assert.NoError(t, err)
require.NoError(t, err)
// Append headers
if c.origin != "" {
@@ -178,7 +181,7 @@ func TestHandler_CORS(t *testing.T) {
// Run the request, do basic checks
resp, err := client.Do(req)
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, c.code, resp.HttpResponse().StatusCode)
// If options and we expect it to be successful, run some checks
+349 -22
View File
@@ -3,9 +3,10 @@ package controller
import (
"context"
"encoding/json"
"errors"
"fmt"
"net/http"
"path"
"os"
"strings"
"time"
@@ -15,7 +16,9 @@ import (
"github.com/hashicorp/watchtower/api"
"github.com/hashicorp/watchtower/globals"
"github.com/hashicorp/watchtower/internal/gen/controller/api/services"
"github.com/hashicorp/watchtower/internal/perms"
"github.com/hashicorp/watchtower/internal/servers/controller/handlers"
"github.com/hashicorp/watchtower/internal/servers/controller/handlers/authenticate"
"github.com/hashicorp/watchtower/internal/servers/controller/handlers/groups"
"github.com/hashicorp/watchtower/internal/servers/controller/handlers/host_catalogs"
"github.com/hashicorp/watchtower/internal/servers/controller/handlers/host_sets"
@@ -24,6 +27,10 @@ import (
"github.com/hashicorp/watchtower/internal/servers/controller/handlers/projects"
"github.com/hashicorp/watchtower/internal/servers/controller/handlers/roles"
"github.com/hashicorp/watchtower/internal/servers/controller/handlers/users"
"github.com/hashicorp/watchtower/internal/types/action"
"github.com/hashicorp/watchtower/internal/types/resource"
"github.com/hashicorp/watchtower/internal/types/scope"
"github.com/kr/pretty"
)
type HandlerProperties struct {
@@ -54,8 +61,7 @@ func handleGrpcGateway(c *Controller) (http.Handler, error) {
// Register*ServiceHandlerServer methods ignore the passed in ctx. Using the baseContext now just in case this changes
// in the future, at which point we'll want to be using the baseContext.
ctx := c.baseContext
mux := runtime.NewServeMux(runtime.WithMetadata(handlers.TokenAuthenticator(c.logger, c.AuthTokenRepoFn)),
runtime.WithProtoErrorHandler(handlers.ErrorHandler(c.logger)))
mux := runtime.NewServeMux(runtime.WithProtoErrorHandler(handlers.ErrorHandler(c.logger)))
hcs, err := host_catalogs.NewService(c.StaticHostRepoFn)
if err != nil {
return nil, fmt.Errorf("failed to create host catalog handler service: %w", err)
@@ -69,6 +75,13 @@ func handleGrpcGateway(c *Controller) (http.Handler, error) {
if err := services.RegisterHostServiceHandlerServer(ctx, mux, &hosts.Service{}); err != nil {
return nil, fmt.Errorf("failed to register host service handler: %w", err)
}
auths, err := authenticate.NewService(c.IamRepoFn, c.AuthTokenRepoFn)
if err != nil {
return nil, fmt.Errorf("failed to create authentication handler service: %w", err)
}
if err := services.RegisterAuthenticationServiceHandlerServer(ctx, mux, auths); err != nil {
return nil, fmt.Errorf("failed to register authenticate service handler: %w", err)
}
os, err := orgs.NewService(c.IamRepoFn)
if err != nil {
return nil, fmt.Errorf("failed to create org handler service: %w", err)
@@ -121,27 +134,76 @@ func wrapHandlerWithCommonFuncs(h http.Handler, c *Controller, props HandlerProp
if maxRequestSize == 0 {
maxRequestSize = globals.DefaultMaxRequestSize
}
var defaultOrgId string
if c != nil && c.conf != nil {
defaultOrgId = c.conf.DefaultOrgId
logUrls := os.Getenv("WATCHTOWER_LOG_URLS") != ""
disableAuthzFailures := c.conf.DisableAuthorizationFailures ||
(c.conf.RawConfig.DevController && os.Getenv("WATCHTOWER_DEV_SKIP_AUTHZ") != "")
if disableAuthzFailures {
c.logger.Warn("AUTHORIZATION CHECKING DISABLED")
}
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if defaultOrgId != "" {
splitPath := strings.Split(r.URL.Path, "/")
if len(splitPath) >= 3 && splitPath[2] == "projects" {
http.Redirect(w, r, path.Join("/v1/orgs", defaultOrgId, strings.Join(splitPath[2:], "/")), 307)
return
}
if logUrls {
c.logger.Trace("request received", "url", r.URL.String())
}
// Set the Cache-Control header for all responses returned
w.Header().Set("Cache-Control", "no-store")
// Start with the request context
ctx := r.Context()
var cancelFunc context.CancelFunc
// Add our timeout
ctx, cancelFunc = context.WithTimeout(ctx, maxRequestDuration)
// Start with the request context and our timeout
ctx, cancelFunc := context.WithTimeout(r.Context(), maxRequestDuration)
defer cancelFunc()
userId := "u_anon"
var res *perms.Resource
var act action.Type
var err error
var authzResults *perms.ACLResults
if r.Method == http.MethodOptions {
// Don't perform authorization checking for preflight requests, at
// least for now. We could add it later if we wanted as an action on
// global or something but likely it would just be enabled/disabled
// per listener instead.
goto AUTHZ_FINISHED
}
// Perform authz checking
res, act, err = decorateAuthParams(r)
if err != nil {
c.logger.Trace("error reading auth parameters from URL", "url", r.URL.Path, "error", err)
// Maybe this isn't the best option, but a URL we can't parse from
// an auth perspective is probably just an invalid URL altogether.
// Treating it as a bad request can be perceived to be less leaky
// than a 404.
w.WriteHeader(http.StatusBadRequest)
return
}
// The resource is only nil with no error if the path is something
// unauthenticated, e.g. the UI serving path.
if res != nil {
authzResults, userId, err = c.performAuthzCheck(ctx, r, res, act)
if err != nil {
c.logger.Error("error during authz check", "error", err)
w.WriteHeader(http.StatusForbidden)
return
}
if userId == "" || !authzResults.Allowed {
// TODO: Decide whether to remove this
if disableAuthzFailures {
c.logger.Info("failed authz info for request", "resource", pretty.Sprint(res), "user_id", userId, "action", act.String())
} else {
w.WriteHeader(http.StatusForbidden)
return
}
}
}
AUTHZ_FINISHED:
// Add the user ID to the context
ctx = context.WithValue(ctx, globals.ContextUserIdValue, userId)
// Add a size limiter if desired
if maxRequestSize > 0 {
ctx = context.WithValue(ctx, "max_request_size", maxRequestSize)
@@ -150,8 +212,6 @@ func wrapHandlerWithCommonFuncs(h http.Handler, c *Controller, props HandlerProp
r = r.WithContext(ctx)
h.ServeHTTP(w, r)
cancelFunc()
return
})
}
@@ -203,8 +263,8 @@ func wrapHandlerWithCors(h http.Handler, props HandlerProperties) http.Handler {
w.WriteHeader(http.StatusForbidden)
err := &api.Error{
Status: api.Int(http.StatusForbidden),
Code: api.String("origin forbidden"),
Status: http.StatusForbidden,
Code: "origin forbidden",
}
enc := json.NewEncoder(w)
@@ -231,10 +291,277 @@ func wrapHandlerWithCors(h http.Handler, props HandlerProperties) http.Handler {
}
h.ServeHTTP(w, req)
return
})
}
func decorateAuthParams(r *http.Request) (*perms.Resource, action.Type, error) {
if r == nil {
return nil, action.Unknown, errors.New("decorate auth params: incoming request is nil")
}
// Remove trailing and leading slashes
trimmedPath := strings.Trim(r.URL.Path, "/")
if !strings.HasPrefix(trimmedPath, "v1") {
// Don't look for auth params for requests to fetch the UI
return nil, action.Unknown, nil
}
splitPath := strings.Split(strings.TrimPrefix(trimmedPath, "v1"), "/")
splitLen := len(splitPath)
if splitLen == 0 {
return nil, action.Unknown, fmt.Errorf("decorate auth params: invalid path")
}
var act action.Type
var typStr string
scp := scope.Global
res := &perms.Resource{
ScopeId: scope.Global.String(),
}
// Handle non-custom types. We'll deal with custom types, including list,
// after parsing the path.
switch r.Method {
case "GET":
act = action.Read
case "POST":
act = action.Create
case "PATCH":
act = action.Update
case "DELETE":
act = action.Delete
default:
return nil, action.Unknown, fmt.Errorf("decorate auth params: unknown method %q", r.Method)
}
// Look for a custom action
colonSplit := strings.Split(splitPath[splitLen-1], ":")
switch len(colonSplit) {
case 1:
// No custom action specified
case 2:
actStr := colonSplit[len(colonSplit)-1]
act = action.Map[actStr]
if act == action.Unknown || act == action.All {
return nil, action.Unknown, fmt.Errorf("decorate auth params: unknown action %q", actStr)
}
// Keep going with the logic without the custom action
splitPath[splitLen-1] = colonSplit[0]
default:
return nil, action.Unknown, fmt.Errorf("decorate auth params: unexpected number of colons in last segment %q", colonSplit[len(colonSplit)-1])
}
// Walk backwards. As we walk backwards we look for scopes and figure out if
// we're operating on a resource or a collection. We also populate the pin.
// The rules for the pin are as follows:
//
// * If the last segment is a collection, the pin is the immediately
// preceding ID
//
// * If the last segment is an ID, the pin is the immediately preceding ID
// not including the last segment
//
// * If at the end of the logic the pin is the id of a scope ("global",
// "o_...", "p_...") then there is no pin. The scopes are already enclosing
// so a pin is redundant.
nextIdIsPin := true
for i := splitLen - 1; i >= 0; i-- {
segment := splitPath[i]
// Collections don't contain underscores; every resource ID does.
segmentIsCollection := !strings.Contains(segment, "_")
if !segmentIsCollection && i != splitLen-1 && nextIdIsPin {
res.Pin = segment
nextIdIsPin = false
}
// Update the scope. Set it to org only if it's at global (that way we
// don't override project with org). We have to check if it's one less
// than the length of the split because operating on the id of a scope
// is actually in the enclosing scope (since you're in the parent scope
// operating on a child scope).
switch segment {
case "projects":
if i < splitLen-2 {
scp = scope.Project
res.ScopeId = splitPath[i+1]
}
case "orgs":
if scp == scope.Global {
if i < splitLen-2 {
scp = scope.Org
res.ScopeId = splitPath[i+1]
}
}
}
if segment == "" {
// This could be the case if we have an action like
// /orgs/o_1234/projects/p_1234/:set-defaults to act on the project
// itself but within its own scope
continue
}
if typStr == "" {
// The resource check takes place inside the type check because if
// we've identified the type we have either already identified the
// right-most resource ID or we're operating on a collection, so
// this prevents us from finding a different ID earlier in the path.
//
// We continue on with the enclosing loop anyways though to ensure
// we find the right scope.
if res.Id == "" && !segmentIsCollection {
res.Id = segment
} else {
// Every collection is the plural of the resource type so drop
// the last 's'
if !strings.HasSuffix(segment, "s") {
return nil, action.Unknown, fmt.Errorf("decorate auth params: invalid collection syntax for %q", segment)
}
typStr = strings.TrimSuffix(segment, "s")
}
}
}
if typStr != "" {
res.Type = resource.Map[typStr]
if res.Type == resource.Unknown {
return nil, action.Unknown, fmt.Errorf("decorate auth params: unknown resource type %q", typStr)
}
} else if res.Id == "" {
return nil, action.Unknown, errors.New("decorate auth params: id and type both not found")
}
// If we're operating on a collection (that is, the ID is blank) and it's a
// GET, it's actually a list
if res.Id == "" && act == action.Read {
act = action.List
}
// If the pin ended up being a scope, nil it out
if res.Pin != "" {
if res.Pin == "global" ||
strings.HasPrefix(res.Pin, "o_") ||
strings.HasPrefix(res.Pin, "p_") {
res.Pin = ""
}
}
return res, act, nil
}
type tokenFormat int
const (
authTokenTypeUnknown tokenFormat = iota
authTokenTypeBearer
authTokenTypeSplitCookie
)
const (
headerAuthMethod = "Authorization"
httpOnlyCookieName = "wt-http-token-cookie"
jsVisibleCookieName = "wt-js-token-cookie"
)
func (c *Controller) performAuthzCheck(ctx context.Context, req *http.Request, res *perms.Resource, act action.Type) (*perms.ACLResults, string, error) {
userId := "u_anon"
if res == nil {
return nil, userId, errors.New("perform authz check: res is nil")
}
var receivedTokenType tokenFormat
var fullToken, token, publicId string
// First, get the token, either from the authorization header or from split
// cookies
{
if authHeader := req.Header.Get("Authorization"); authHeader != "" {
headerSplit := strings.SplitN(strings.TrimSpace(authHeader), " ", 2)
if len(headerSplit) == 2 && strings.EqualFold(strings.TrimSpace(headerSplit[0]), "bearer") {
receivedTokenType = authTokenTypeBearer
fullToken = strings.TrimSpace(headerSplit[1])
}
}
if receivedTokenType != authTokenTypeBearer {
var httpCookiePayload string
var jsCookiePayload string
if hc, err := req.Cookie(httpOnlyCookieName); err == nil {
httpCookiePayload = hc.Value
}
if jc, err := req.Cookie(jsVisibleCookieName); err == nil {
jsCookiePayload = jc.Value
}
if httpCookiePayload != "" && jsCookiePayload != "" {
receivedTokenType = authTokenTypeSplitCookie
fullToken = jsCookiePayload + httpCookiePayload
}
}
if receivedTokenType == authTokenTypeUnknown || fullToken == "" {
// We didn't find auth info or a client screwed up and put in a
// blank header instead of nothing at all, so carry on as the
// anonymous user
goto GRANTSLOOKUP
}
splitFullToken := strings.Split(fullToken, "_")
if len(splitFullToken) != 3 {
return nil, userId, fmt.Errorf("perform authz check: unexpected number of segments in token, expected %d, found %d", 3, len(splitFullToken))
}
token = splitFullToken[2]
publicId = strings.Join(splitFullToken[0:2], "_")
if receivedTokenType == authTokenTypeUnknown || token == "" || publicId == "" {
return nil, userId, fmt.Errorf("perform authz check: after parsing, could not find valid token")
}
}
// Validate the token and fetch the corresponding user ID
{
tokenRepo, err := c.AuthTokenRepoFn()
if err != nil {
return nil, userId, fmt.Errorf("perform authz check: failed to get authtoken repo: %w", err)
}
at, err := tokenRepo.ValidateToken(ctx, publicId, token)
if err != nil {
return nil, userId, fmt.Errorf("perform authz check: failed to validate token: %w", err)
}
if at != nil {
userId = at.GetIamUserId()
}
}
GRANTSLOOKUP:
var parsedGrants []perms.Grant
var grantPairs []perms.GrantPair
// Fetch and parse grants for this user ID
{
iamRepo, err := c.IamRepoFn()
if err != nil {
return nil, userId, fmt.Errorf("perform authz check: failed to get iam repo: %w", err)
}
grantPairs, err = iamRepo.GrantsForUser(ctx, userId)
if err != nil {
return nil, userId, fmt.Errorf("perform authz check: failed to query for user grants: %w", err)
}
parsedGrants = make([]perms.Grant, 0, len(grantPairs))
for _, pair := range grantPairs {
parsed, err := perms.Parse(pair.ScopeId, userId, pair.Grant)
if err != nil {
return nil, userId, fmt.Errorf("perform authz check: failed to parse grant %#v: %w", pair.Grant, err)
}
parsedGrants = append(parsedGrants, parsed)
}
}
acl := perms.NewACL(parsedGrants...)
allowed := acl.Allowed(*res, act)
return &allowed, userId, nil
}
/*
func WrapForwardedForHandler(h http.Handler, authorizedAddrs []*sockaddr.SockAddrMarshaler, rejectNotPresent, rejectNonAuthz bool, hopSkips int) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+251 -4
View File
@@ -2,13 +2,18 @@ package controller
import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/http/httptest"
"strings"
"testing"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
"github.com/hashicorp/watchtower/internal/gen/controller/api/services"
"github.com/hashicorp/watchtower/internal/types/action"
"github.com/hashicorp/watchtower/internal/types/resource"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@@ -119,6 +124,28 @@ func TestGrpcGatewayRouting(t *testing.T) {
}
}
func TestAuthenticationHandler(t *testing.T) {
c := NewTestController(t, &TestControllerOpts{DefaultOrgId: "o_1234567890"})
defer c.Shutdown()
resp, err := http.Post(fmt.Sprintf("%s/v1/orgs/o_1234567890/auth-methods/am_1234567890:authenticate", c.ApiAddrs()[0]), "application/json",
strings.NewReader(`{"token_type": null, "credentials": {"name":"test", "password": "test"}}`))
require.NoError(t, err)
assert.Equal(t, http.StatusOK, resp.StatusCode, "Got response: %v", resp)
b, err := ioutil.ReadAll(resp.Body)
require.NoError(t, err)
body := make(map[string]interface{})
require.NoError(t, json.Unmarshal(b, &body))
require.Contains(t, body, "id")
require.Contains(t, body, "token")
pubId, tok := body["id"].(string), body["token"].(string)
assert.NotEmpty(t, pubId)
assert.NotEmpty(t, tok)
assert.Truef(t, strings.HasPrefix(tok, pubId), "Token: %q, Id: %q", tok, pubId)
}
func TestGrpcGatewayRouting_CustomActions(t *testing.T) {
ctx := context.Background()
// The unimplemented result indicates the grpc routing is happening successfully otherwise it would return NotFound.
@@ -167,7 +194,9 @@ func TestGrpcGatewayRouting_CustomActions(t *testing.T) {
}
func TestHandleGrpcGateway(t *testing.T) {
c := NewTestController(t, nil)
c := NewTestController(t, &TestControllerOpts{
DisableAuthorizationFailures: true,
})
defer c.Shutdown()
cases := []struct {
@@ -177,12 +206,12 @@ func TestHandleGrpcGateway(t *testing.T) {
}{
{
"Non existent path",
"v1/this-is-made-up",
http.StatusNotFound,
"v1/this-is-made-ups",
http.StatusBadRequest,
},
{
"Unimplemented path",
"v1/orgs/1/projects/2/host-catalogs/3/host-sets/4",
"v1/orgs/1/projects/2/host-catalogs/3/host-sets/hs_4",
http.StatusMethodNotAllowed,
},
}
@@ -200,3 +229,221 @@ func TestHandleGrpcGateway(t *testing.T) {
})
}
}
func TestHandler_AuthDecoration(t *testing.T) {
cases := []struct {
name string
path string
method string
action action.Type
scope string
resource resource.Type
id string
pin string
wantErrContains string
}{
{
name: "global scope, read, with id",
path: "/v1/users/u_anon",
method: "GET",
action: action.Read,
scope: "global",
resource: resource.User,
id: "u_anon",
},
{
name: "global scope, update, with id",
path: "/v1/auth-methods/am_1234",
method: "PATCH",
action: action.Update,
scope: "global",
resource: resource.AuthMethod,
id: "am_1234",
},
{
name: "global scope, delete",
path: "/v1/orgs/o_1234",
method: "DELETE",
action: action.Delete,
scope: "global",
resource: resource.Org,
id: "o_1234",
},
{
name: "global scope, create",
path: "/v1/roles",
method: "POST",
action: action.Create,
scope: "global",
resource: resource.Role,
},
{
name: "global, invalid collection syntax",
path: "/v1/org",
wantErrContains: "invalid collection syntax",
},
{
name: "global, custom action",
path: "/v1/orgs/o_123/auth-methods/am_1234:authenticate",
method: "POST",
action: action.Authenticate,
scope: "o_123",
resource: resource.AuthMethod,
id: "am_1234",
},
{
name: "root, unknown action",
path: "/v1/:authentifake",
wantErrContains: "unknown action",
},
{
name: "root, unknown empty action",
path: "/v1/:",
wantErrContains: "unknown action",
},
{
name: "root, invalid method",
path: "/v1/:authenticate",
method: "FOOBAR",
wantErrContains: "unknown method",
},
{
name: "root, wrong number of colons",
path: "/v1/:auth:enticate",
wantErrContains: "unexpected number of colons",
},
{
name: "org scope, valid",
path: "/v1/orgs/o_abc123/auth-methods",
method: "POST",
action: action.Create,
scope: "o_abc123",
resource: resource.AuthMethod,
},
{
name: "project scope, valid",
path: "/v1/orgs/o_abc123/projects/p_1234/host-catalogs",
method: "POST",
action: action.Create,
scope: "p_1234",
resource: resource.HostCatalog,
},
{
name: "project scope, action on project",
path: "/v1/orgs/o_abc123/projects/p_1234/:set-principals",
method: "POST",
action: action.SetPrincipals,
scope: "p_1234",
resource: resource.Project,
id: "p_1234",
},
{
name: "org scope, action on project",
path: "/v1/orgs/o_abc123/projects/p_1234:set-principals",
method: "POST",
action: action.SetPrincipals,
scope: "o_abc123",
resource: resource.Project,
id: "p_1234",
},
{
name: "org scope, get on collection is list",
path: "/v1/orgs/o_abc123/projects",
action: action.List,
scope: "o_abc123",
resource: resource.Project,
},
{
name: "org scope, action on org",
path: "/v1/orgs/o_abc123/:deauthenticate",
action: action.Deauthenticate,
scope: "o_abc123",
resource: resource.Org,
id: "o_abc123",
},
{
name: "top level action, invalid",
path: "/v1/:read",
wantErrContains: "id and type both not found",
},
{
name: "top level, invalid",
path: "/v1/",
wantErrContains: "id and type both not found",
},
{
name: "non-api path",
path: "/",
},
{
name: "project scope, pinning collection",
path: "/v1/orgs/o_abc123/projects/p_1234/host-catalogs/hc_1234/host-sets",
action: action.List,
scope: "p_1234",
pin: "hc_1234",
resource: resource.HostSet,
},
{
name: "project scope, pinning collection, custom action",
path: "/v1/orgs/o_abc123/projects/p_1234/host-catalogs/hc_1234/host-sets:create",
action: action.Create,
scope: "p_1234",
pin: "hc_1234",
resource: resource.HostSet,
},
{
name: "project scope, pinning id",
path: "/v1/orgs/o_abc123/projects/p_1234/host-catalogs/hc_1234/host-sets/hs_abc",
action: action.Read,
id: "hs_abc",
scope: "p_1234",
pin: "hc_1234",
resource: resource.HostSet,
},
{
name: "project scope, pinning id, custom action",
path: "/v1/orgs/o_abc123/projects/p_1234/host-catalogs/hc_1234/host-sets/hs_abc:update",
action: action.Update,
id: "hs_abc",
scope: "p_1234",
pin: "hc_1234",
resource: resource.HostSet,
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
require, assert := require.New(t), assert.New(t)
if tc.method == "" {
tc.method = "GET"
}
req, err := http.NewRequest(tc.method, fmt.Sprintf("http://127.0.0.1:9200:%s", tc.path), nil)
require.NoError(err)
res, act, err := decorateAuthParams(nil)
assert.Nil(res)
require.Error(err)
assert.Equal(action.Unknown, act)
assert.Contains(err.Error(), "incoming request is nil")
res, act, err = decorateAuthParams(req)
if tc.wantErrContains != "" {
require.Error(err)
assert.Contains(err.Error(), tc.wantErrContains, err.Error())
return
}
require.NoError(err)
if tc.path == "/" {
return
}
require.NotNil(res)
require.NotEqual(action.Unknown, act)
assert.Equal(tc.scope, res.ScopeId, "scope")
assert.Equal(tc.action, act, "action")
assert.Equal(tc.resource, res.Type, "type")
assert.Equal(tc.id, res.Id, "id")
assert.Equal(tc.pin, res.Pin, "pin")
})
}
}
@@ -0,0 +1,164 @@
package authenticate
import (
"context"
"crypto/sha256"
"encoding/base32"
"fmt"
"regexp"
"strings"
"sync/atomic"
"github.com/hashicorp/watchtower/internal/authtoken"
"github.com/hashicorp/watchtower/internal/db"
pba "github.com/hashicorp/watchtower/internal/gen/controller/api/resources/authtokens"
pbs "github.com/hashicorp/watchtower/internal/gen/controller/api/services"
"github.com/hashicorp/watchtower/internal/iam"
iamStore "github.com/hashicorp/watchtower/internal/iam/store"
"github.com/hashicorp/watchtower/internal/servers/controller/common"
"github.com/hashicorp/watchtower/internal/servers/controller/handlers"
"github.com/hashicorp/watchtower/internal/types/scope"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
const orgIdFieldName = "org_id"
var (
reInvalidID = regexp.MustCompile("[^A-Za-z0-9]")
// TODO: Remove once auth methods are in
OrgScope string
RWDb = new(atomic.Value)
)
func init() {
RWDb.Store((*db.Db)(nil))
}
// Service handles request as described by the pbs.OrgServiceServer interface.
type Service struct {
iamRepo common.IamRepoFactory
authTokenRepo common.AuthTokenRepoFactory
}
// NewService returns an org service which handles org related requests to watchtower.
func NewService(iamRepo common.IamRepoFactory, atRepo common.AuthTokenRepoFactory) (Service, error) {
if iamRepo == nil {
return Service{}, fmt.Errorf("nil iam repository provided")
}
if atRepo == nil {
return Service{}, fmt.Errorf("nil auth token repository provided")
}
return Service{iamRepo: iamRepo, authTokenRepo: atRepo}, nil
}
var _ pbs.AuthenticationServiceServer = Service{}
// Authenticate implements the interface pbs.AuthenticationServiceServer.
func (s Service) Authenticate(ctx context.Context, req *pbs.AuthenticateRequest) (*pbs.AuthenticateResponse, error) {
if err := validateAuthenticateRequest(req); err != nil {
return nil, err
}
tok, err := s.authenticateWithRepo(ctx, req)
if err != nil {
return nil, err
}
return &pbs.AuthenticateResponse{Item: tok}, nil
}
// Deauthenticate implements the interface pbs.AuthenticationServiceServer.
func (s Service) Deauthenticate(ctx context.Context, req *pbs.DeauthenticateRequest) (*pbs.DeauthenticateResponse, error) {
return nil, status.Error(codes.Unimplemented, "Requested method is unimplemented for Org.")
}
func (s Service) authenticateWithRepo(ctx context.Context, req *pbs.AuthenticateRequest) (*pba.AuthToken, error) {
userRepo, err := s.iamRepo()
if err != nil {
return nil, err
}
atRepo, err := s.authTokenRepo()
if err != nil {
return nil, err
}
// Place holder for making a request to authenticate
creds := req.GetCredentials().GetFields()
pwName, password := creds["name"], creds["password"]
if pwName.GetStringValue() == "wrong" && password.GetStringValue() == "wrong" {
return nil, status.Error(codes.Unauthenticated, "Unable to authenticate.")
}
// Get back a password.Account with a CredentialId string and a public Id
// Create a fake auth account ID for the moment
acctIdBytes := sha256.Sum256([]byte(pwName.GetStringValue()))
acctId := fmt.Sprintf("aa_%s", base32.StdEncoding.EncodeToString(acctIdBytes[:])[0:10])
aAcct := &iam.AuthAccount{AuthAccount: &iamStore.AuthAccount{
PublicId: acctId,
ScopeId: OrgScope,
AuthMethodId: req.AuthMethodId,
}}
RWDb.Load().(*db.Db).Create(ctx, aAcct)
u, err := userRepo.LookupUserWithLogin(ctx, acctId, iam.WithAutoVivify(true))
if err != nil {
return nil, err
}
tok, err := atRepo.CreateAuthToken(ctx, u.GetPublicId(), acctId)
if err != nil {
return nil, err
}
tok.Token = tok.GetPublicId() + "_" + tok.GetToken()
return toProto(tok), nil
}
func toProto(t *authtoken.AuthToken) *pba.AuthToken {
return &pba.AuthToken{
Id: t.GetPublicId(),
Token: t.GetToken(),
UserId: t.GetIamUserId(),
AuthMethodId: t.GetAuthMethodId(),
CreatedTime: t.GetCreateTime().GetTimestamp(),
UpdatedTime: t.GetUpdateTime().GetTimestamp(),
ApproximateLastUsedTime: t.GetApproximateLastAccessTime().GetTimestamp(),
ExpirationTime: t.GetExpirationTime().GetTimestamp(),
}
}
// A validateX method should exist for each method above. These methods do not make calls to any backing service but enforce
// requirements on the structure of the request. They verify that:
// * The path passed in is correctly formatted
// * All required parameters are set
// * There are no conflicting parameters provided
func validateAuthenticateRequest(req *pbs.AuthenticateRequest) error {
badFields := make(map[string]string)
if !validId(req.GetOrgId(), scope.Org.Prefix()+"_") {
badFields[orgIdFieldName] = "Invalid formatted identifier."
}
if strings.TrimSpace(req.GetAuthMethodId()) == "" {
badFields["auth_method_id"] = "This is a required field."
} else if validId(req.GetAuthMethodId(), "am") {
badFields["auth_method_id"] = "Invalid formatted identifier."
}
// TODO: Update this when we enable different auth method types.
if req.GetCredentials() == nil {
badFields["credentials"] = "This is a required field."
}
// TODO: Update this when we enable split cookie token types.
tType := strings.ToLower(strings.TrimSpace(req.GetTokenType()))
if tType != "" && tType != "token" {
badFields["token_type"] = "The only accepted type is 'token'."
}
if len(badFields) > 0 {
return handlers.InvalidArgumentErrorf("Invalid fields provided in request.", badFields)
}
return nil
}
func validId(id, prefix string) bool {
if !strings.HasPrefix(id, prefix) {
return false
}
id = strings.TrimPrefix(id, prefix)
return !reInvalidID.Match([]byte(id))
}
@@ -0,0 +1,236 @@
package authenticate
import (
"context"
"crypto/sha256"
"encoding/base32"
"fmt"
"strings"
"testing"
structpb "github.com/golang/protobuf/ptypes/struct"
"github.com/hashicorp/watchtower/internal/authtoken"
"github.com/hashicorp/watchtower/internal/db"
pba "github.com/hashicorp/watchtower/internal/gen/controller/api/resources/authtokens"
pbs "github.com/hashicorp/watchtower/internal/gen/controller/api/services"
"github.com/hashicorp/watchtower/internal/iam"
iamStore "github.com/hashicorp/watchtower/internal/iam/store"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
func getAuthMethodAndAccountId(t *testing.T, org *iam.Scope, rw *db.Db) (string, string) {
// TODO: Remove this when Auth Account repo is in place.
insert := `insert into auth_method
(public_id, scope_id)
values
($1, $2);`
amId, err := db.NewPublicId("am")
require.NoError(t, err)
innerDb, err := rw.DB()
require.NoError(t, err)
_, err = innerDb.Exec(insert, amId, org.GetPublicId())
require.NoError(t, err)
aAcctId, err := db.NewPublicId("aa")
require.NoError(t, err)
aAcct := &iam.AuthAccount{AuthAccount: &iamStore.AuthAccount{
PublicId: aAcctId,
ScopeId: org.GetPublicId(),
AuthMethodId: amId,
}}
require.NoError(t, rw.Create(context.Background(), aAcct))
return aAcct.GetAuthMethodId(), aAcct.GetPublicId()
}
func TestAuthenticate(t *testing.T) {
conn, _ := db.TestSetup(t, "postgres")
rw := db.New(conn)
RWDb.Store(rw)
wrapper := db.TestWrapper(t)
o, _ := iam.TestScopes(t, conn)
authTokenRepoFn := func() (*authtoken.Repository, error) { return authtoken.NewRepository(rw, rw, wrapper) }
iamRepoFn := func() (*iam.Repository, error) { return iam.NewRepository(rw, rw, wrapper) }
amId, _ := getAuthMethodAndAccountId(t, o, rw)
cases := []struct {
name string
request *pbs.AuthenticateRequest
want *pbs.AuthenticateResponse
wantErr error
}{
{
name: "basic",
request: &pbs.AuthenticateRequest{
OrgId: o.GetPublicId(),
AuthMethodId: amId,
TokenType: "token",
Credentials: func() *structpb.Struct {
creds := map[string]*structpb.Value{
"name": {Kind: &structpb.Value_StringValue{StringValue: "admin"}},
"password": {Kind: &structpb.Value_StringValue{StringValue: "hunter2"}},
}
return &structpb.Struct{Fields: creds}
}(),
},
want: &pbs.AuthenticateResponse{Item: &pba.AuthToken{
AuthMethodId: amId,
}},
},
{
name: "no-token-type",
request: &pbs.AuthenticateRequest{
OrgId: o.GetPublicId(),
AuthMethodId: amId,
Credentials: func() *structpb.Struct {
creds := map[string]*structpb.Value{
"name": {Kind: &structpb.Value_StringValue{StringValue: "admin"}},
"password": {Kind: &structpb.Value_StringValue{StringValue: "hunter2"}},
}
return &structpb.Struct{Fields: creds}
}(),
},
want: &pbs.AuthenticateResponse{Item: &pba.AuthToken{
AuthMethodId: amId,
}},
},
{
name: "bad-token-type",
request: &pbs.AuthenticateRequest{
OrgId: o.GetPublicId(),
AuthMethodId: amId,
TokenType: "email",
Credentials: func() *structpb.Struct {
creds := map[string]*structpb.Value{
"name": {Kind: &structpb.Value_StringValue{StringValue: "admin"}},
"password": {Kind: &structpb.Value_StringValue{StringValue: "hunter2"}},
}
return &structpb.Struct{Fields: creds}
}(),
},
wantErr: status.Error(codes.InvalidArgument, "invalid argument"),
},
{
name: "no-authmethod",
request: &pbs.AuthenticateRequest{
OrgId: o.GetPublicId(),
Credentials: func() *structpb.Struct {
creds := map[string]*structpb.Value{
"name": {Kind: &structpb.Value_StringValue{StringValue: "admin"}},
"password": {Kind: &structpb.Value_StringValue{StringValue: "hunter2"}},
}
return &structpb.Struct{Fields: creds}
}(),
},
wantErr: status.Error(codes.InvalidArgument, "invalid argument"),
},
{
name: "wrong-username-password",
request: &pbs.AuthenticateRequest{
OrgId: o.GetPublicId(),
AuthMethodId: amId,
TokenType: "token",
Credentials: func() *structpb.Struct {
creds := map[string]*structpb.Value{
"name": {Kind: &structpb.Value_StringValue{StringValue: "wrong"}},
"password": {Kind: &structpb.Value_StringValue{StringValue: "wrong"}},
}
return &structpb.Struct{Fields: creds}
}(),
},
wantErr: status.Error(codes.Unauthenticated, "unauthenticated"),
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
s, err := NewService(iamRepoFn, authTokenRepoFn)
require.NoError(err)
// TODO: remove when we stop faking things
name := tc.request.Credentials.Fields["name"].GetStringValue()
acctIdBytes := sha256.Sum256([]byte(name))
acctId := fmt.Sprintf("aa_%s", base32.StdEncoding.EncodeToString(acctIdBytes[:])[0:10])
aAcct := &iam.AuthAccount{AuthAccount: &iamStore.AuthAccount{
PublicId: acctId,
ScopeId: o.PublicId,
AuthMethodId: amId,
}}
RWDb.Load().(*db.Db).Create(context.Background(), aAcct)
resp, err := s.Authenticate(context.Background(), tc.request)
if tc.wantErr != nil {
assert.Error(err)
assert.Equal(status.Code(tc.wantErr), status.Code(err))
return
}
require.NoError(err)
aToken := resp.GetItem()
assert.NotEmpty(aToken.GetId())
assert.NotEmpty(aToken.GetToken())
assert.True(strings.HasPrefix(aToken.GetToken(), aToken.GetId()))
assert.Equal(amId, aToken.GetAuthMethodId())
assert.Equal(aToken.GetCreatedTime(), aToken.GetUpdatedTime())
assert.Equal(aToken.GetCreatedTime(), aToken.GetApproximateLastUsedTime())
})
}
}
func TestAuthenticate_AuthAccountConnectedToIamUser(t *testing.T) {
assert, require := assert.New(t), require.New(t)
conn, _ := db.TestSetup(t, "postgres")
rw := db.New(conn)
RWDb.Store(rw)
wrapper := db.TestWrapper(t)
o, _ := iam.TestScopes(t, conn)
authTokenRepoFn := func() (*authtoken.Repository, error) { return authtoken.NewRepository(rw, rw, wrapper) }
iamRepoFn := func() (*iam.Repository, error) { return iam.NewRepository(rw, rw, wrapper) }
iamRepo, err := iamRepoFn()
require.NoError(err)
// connected to an account.
amId, _ := getAuthMethodAndAccountId(t, o, rw)
name := "admin"
acctIdBytes := sha256.Sum256([]byte(name))
acctId := fmt.Sprintf("aa_%s", base32.StdEncoding.EncodeToString(acctIdBytes[:])[0:10])
aAcct := &iam.AuthAccount{AuthAccount: &iamStore.AuthAccount{
PublicId: acctId,
ScopeId: o.PublicId,
AuthMethodId: amId,
}}
RWDb.Load().(*db.Db).Create(context.Background(), aAcct)
iamUser, err := iamRepo.LookupUserWithLogin(context.Background(), acctId, iam.WithAutoVivify(true))
require.NoError(err)
s, err := NewService(iamRepoFn, authTokenRepoFn)
require.NoError(err)
resp, err := s.Authenticate(context.Background(), &pbs.AuthenticateRequest{
OrgId: o.GetPublicId(),
AuthMethodId: amId,
Credentials: func() *structpb.Struct {
creds := map[string]*structpb.Value{
"name": {Kind: &structpb.Value_StringValue{StringValue: name}},
"password": {Kind: &structpb.Value_StringValue{StringValue: "hunter2"}},
}
return &structpb.Struct{Fields: creds}
}(),
})
require.NoError(err)
aToken := resp.GetItem()
assert.Equal(iamUser.GetPublicId(), aToken.GetUserId())
assert.Equal(amId, aToken.GetAuthMethodId())
assert.NotEmpty(aToken.GetId())
assert.NotEmpty(aToken.GetToken())
assert.True(strings.HasPrefix(aToken.GetToken(), aToken.GetId()))
}
@@ -21,46 +21,110 @@ const (
// TokenAuthenticator returns a function that can be used in grpc-gateway's runtime.WithMetadata ServerOption.
// It looks at the cookies and headers of the incoming request and returns metadata that can later be
// used by handlers to build a TokenMetadata using the ToTokenMetadata function.
func TokenAuthenticator(l hclog.Logger, tokenRepo common.AuthTokenRepoFactory) func(context.Context, *http.Request) metadata.MD {
func TokenAuthenticator(l hclog.Logger, tokenRepo common.AuthTokenRepoFactory, iamRepo common.IamRepoFactory) func(context.Context, *http.Request) metadata.MD {
return func(ctx context.Context, req *http.Request) metadata.MD {
tMD := TokenMetadata{}
if authHeader := req.Header.Get(headerAuthMethod); authHeader != "" {
headerSplit := strings.SplitN(strings.TrimSpace(authHeader), " ", 2)
if len(headerSplit) == 2 && strings.EqualFold(strings.TrimSpace(headerSplit[0]), "bearer") {
tMD.recievedTokenType = authTokenTypeBearer
tMD.bearerPayload = strings.TrimSpace(headerSplit[1])
return TokenMetadata{}.toMetadata()
/*
tMD := TokenMetadata{}
if authHeader := req.Header.Get(headerAuthMethod); authHeader != "" {
headerSplit := strings.SplitN(strings.TrimSpace(authHeader), " ", 2)
if len(headerSplit) == 2 && strings.EqualFold(strings.TrimSpace(headerSplit[0]), "bearer") {
tMD.receivedTokenType = authTokenTypeBearer
tMD.bearerPayload = strings.TrimSpace(headerSplit[1])
}
}
}
if tMD.recievedTokenType != authTokenTypeBearer {
if hc, err := req.Cookie(httpOnlyCookieName); err == nil {
tMD.httpCookiePayload = hc.Value
if tMD.receivedTokenType != authTokenTypeBearer {
if hc, err := req.Cookie(httpOnlyCookieName); err == nil {
tMD.httpCookiePayload = hc.Value
}
if jc, err := req.Cookie(jsVisibleCookieName); err == nil {
tMD.jsCookiePayload = jc.Value
}
if tMD.httpCookiePayload != "" && tMD.jsCookiePayload != "" {
tMD.receivedTokenType = authTokenTypeSplitCookie
}
}
if jc, err := req.Cookie(jsVisibleCookieName); err == nil {
tMD.jsCookiePayload = jc.Value
}
if tMD.httpCookiePayload != "" && tMD.jsCookiePayload != "" {
tMD.recievedTokenType = authTokenTypeSplitCookie
}
}
if tMD.recievedTokenType == authTokenTypeUnknown || tMD.token() == "" || tMD.publicId() == "" {
if tMD.receivedTokenType == authTokenTypeUnknown || tMD.token() == "" || tMD.publicId() == "" {
return tMD.toMetadata()
}
tokenRepo, err := tokenRepo()
if err != nil {
l.Error("failed to get authtoken repo", "error", err)
return tMD.toMetadata()
}
at, err := tokenRepo.ValidateToken(ctx, tMD.publicId(), tMD.token())
if err != nil {
l.Error("failed to validate token", "error", err)
}
if at != nil {
tMD.UserId = at.GetIamUserId()
} else {
tMD.UserId = "u_anon"
}
iamRepo, err := iamRepo()
if err != nil {
l.Error("failed to get iam repo", "error", err)
return tMD.toMetadata()
}
grantPairs, err := iamRepo.GrantsForUser(ctx, tMD.UserId)
if err != nil {
l.Error("failed to query for user grants", "error", err)
return tMD.toMetadata()
}
parsedGrants := make([]perms.Grant, 0, len(grantPairs))
for _, pair := range grantPairs {
parsed, err := perms.Parse(pair.ScopeId, tMD.UserId, pair.Grant)
if err != nil {
l.Error("failed to parse grant", "grant", pair.Grant, "error", err)
return tMD.toMetadata()
}
parsedGrants = append(parsedGrants, parsed)
}
var scopeId, id, pin string
var typ resource.Type
var act action.Type
typRaw := ctx.Value(globals.ContextTypeValue)
if typRaw != nil {
typ = typRaw.(resource.Type)
}
scopeIdRaw := ctx.Value(globals.ContextScopeValue)
if scopeIdRaw != nil {
scopeId = scopeIdRaw.(string)
}
actRaw := ctx.Value(globals.ContextActionValue)
if actRaw != nil {
act = actRaw.(action.Type)
}
idRaw := ctx.Value(globals.ContextResourceValue)
if idRaw != nil {
id = idRaw.(string)
}
pinRaw := ctx.Value(globals.ContextPinValue)
if pinRaw != nil {
pin = pinRaw.(string)
}
acl := perms.NewACL(parsedGrants...)
res := perms.Resource{
// These values were parsed from the request information
ScopeId: scopeId,
Type: typ,
Id: id,
Pin: pin,
}
allowed := acl.Allowed(res, act)
if allowed.Allowed {
tMD.authorized = true
}
l.Info("grant checking", "user_id", tMD.UserId, "grants", pretty.Sprint(grantPairs), "resource", res, "authorized", allowed)
return tMD.toMetadata()
}
repo, err := tokenRepo()
if err != nil {
l.Error("failed to get authtoken repo", "error", err)
return tMD.toMetadata()
}
at, err := repo.ValidateToken(ctx, tMD.publicId(), tMD.token())
if err != nil {
l.Error("failed to validate token", "error", err)
}
if at != nil {
tMD.UserId = at.GetIamUserId()
}
return tMD.toMetadata()
*/
}
}
@@ -87,7 +151,9 @@ type TokenMetadata struct {
// Only set the UserId if the token was found and was not expired.
UserId string
recievedTokenType tokenFormat
authorized bool
receivedTokenType tokenFormat
bearerPayload string
jsCookiePayload string
@@ -96,6 +162,7 @@ type TokenMetadata struct {
const (
mdAuthTokenUserKey = "wt-authtoken-user-key"
mdAuthAuthorizedKey = "wt-authtoken-authorized"
mdAuthTokenBearerTokenKey = "wt-authtoken-bearer-token-key"
mdAuthTokenHttpTokenKey = "wt-authtoken-http-token-key"
mdAuthTokenJsTokenKey = "wt-authtoken-js-token-key"
@@ -113,6 +180,9 @@ func ToTokenMetadata(ctx context.Context) TokenMetadata {
if uid := md.Get(mdAuthTokenUserKey); len(uid) > 0 {
tMD.UserId = uid[0]
}
if authzd := md.Get(mdAuthAuthorizedKey); len(authzd) > 0 {
tMD.authorized = authzd[0] == "true"
}
if token := md.Get(mdAuthTokenBearerTokenKey); len(token) > 0 {
tMD.bearerPayload = token[0]
}
@@ -124,7 +194,7 @@ func ToTokenMetadata(ctx context.Context) TokenMetadata {
}
if sType := md.Get(mdAuthTokenTypeKey); len(sType) > 0 {
if st, err := strconv.Atoi(sType[0]); err == nil {
tMD.recievedTokenType = tokenFormat(st)
tMD.receivedTokenType = tokenFormat(st)
}
}
@@ -136,6 +206,11 @@ func (s TokenMetadata) toMetadata() metadata.MD {
if s.UserId != "" {
md.Set(mdAuthTokenUserKey, s.UserId)
}
if s.authorized {
md.Set(mdAuthAuthorizedKey, "true")
} else {
md.Set(mdAuthAuthorizedKey, "false")
}
if s.bearerPayload != "" {
md.Set(mdAuthTokenBearerTokenKey, s.bearerPayload)
}
@@ -145,9 +220,10 @@ func (s TokenMetadata) toMetadata() metadata.MD {
if s.jsCookiePayload != "" {
md.Set(mdAuthTokenJsTokenKey, s.jsCookiePayload)
}
if s.recievedTokenType != authTokenTypeUnknown {
md.Set(mdAuthTokenTypeKey, fmt.Sprint(s.recievedTokenType))
if s.receivedTokenType != authTokenTypeUnknown {
md.Set(mdAuthTokenTypeKey, fmt.Sprint(s.receivedTokenType))
}
return md
}
@@ -155,7 +231,7 @@ func (s TokenMetadata) toMetadata() metadata.MD {
// is malformed then this returns an empty string.
func (s TokenMetadata) publicId() string {
tok := ""
switch s.recievedTokenType {
switch s.receivedTokenType {
case authTokenTypeBearer:
tok = s.bearerPayload
case authTokenTypeSplitCookie:
@@ -172,7 +248,7 @@ func (s TokenMetadata) publicId() string {
// is malformed then this returns an empty string.
func (s TokenMetadata) token() string {
var tok string
switch s.recievedTokenType {
switch s.receivedTokenType {
case authTokenTypeBearer:
tok = s.bearerPayload
case authTokenTypeSplitCookie:
@@ -14,6 +14,7 @@ import (
"github.com/hashicorp/watchtower/internal/db"
"github.com/hashicorp/watchtower/internal/gen/controller/api/services"
pbs "github.com/hashicorp/watchtower/internal/gen/controller/api/services"
"github.com/hashicorp/watchtower/internal/iam"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@@ -30,6 +31,7 @@ func (s *fakeHandler) GetOrg(ctx context.Context, _ *pbs.GetOrgRequest) (*pbs.Ge
}
func TestAuthTokenPublicIdTokenValue(t *testing.T) {
t.Skip("functionality has moved for now")
cases := []struct {
name string
in TokenMetadata
@@ -39,7 +41,7 @@ func TestAuthTokenPublicIdTokenValue(t *testing.T) {
{
name: "no delimeter",
in: TokenMetadata{
recievedTokenType: authTokenTypeBearer,
receivedTokenType: authTokenTypeBearer,
bearerPayload: "prefix_publicid_token",
jsCookiePayload: "this_is_just_junk",
httpCookiePayload: "this_can_be_ignored",
@@ -50,7 +52,7 @@ func TestAuthTokenPublicIdTokenValue(t *testing.T) {
{
name: "no delimeter",
in: TokenMetadata{
recievedTokenType: authTokenTypeSplitCookie,
receivedTokenType: authTokenTypeSplitCookie,
bearerPayload: "this_is_just_junk_that_should_be_ignored",
jsCookiePayload: "prefix_publicid_token",
httpCookiePayload: "cookiepayload",
@@ -61,7 +63,7 @@ func TestAuthTokenPublicIdTokenValue(t *testing.T) {
{
name: "no delimeter",
in: TokenMetadata{
recievedTokenType: authTokenTypeBearer,
receivedTokenType: authTokenTypeBearer,
bearerPayload: "this-doesnt-have-the-expected-delimiter",
},
wantId: "",
@@ -70,7 +72,7 @@ func TestAuthTokenPublicIdTokenValue(t *testing.T) {
{
name: "to many delimeters",
in: TokenMetadata{
recievedTokenType: authTokenTypeBearer,
receivedTokenType: authTokenTypeBearer,
bearerPayload: "this_has_to_many_delimiters",
},
wantId: "",
@@ -87,13 +89,19 @@ func TestAuthTokenPublicIdTokenValue(t *testing.T) {
}
func TestAuthTokenAuthenticator(t *testing.T) {
t.Skip("functionality has moved for now")
conn, _ := db.TestSetup(t, "postgres")
rw := db.New(conn)
wrapper := db.TestWrapper(t)
repo, err := authtoken.NewRepository(rw, rw, wrapper)
tokenRepo, err := authtoken.NewRepository(rw, rw, wrapper)
require.NoError(t, err)
repoFn := func() (*authtoken.Repository, error) {
return repo, nil
iamRepo, err := iam.NewRepository(rw, rw, wrapper)
require.NoError(t, err)
tokenRepoFn := func() (*authtoken.Repository, error) {
return tokenRepo, nil
}
iamRepoFn := func() (*iam.Repository, error) {
return iamRepo, nil
}
at := authtoken.TestAuthToken(t, conn, wrapper)
@@ -110,13 +118,13 @@ func TestAuthTokenAuthenticator(t *testing.T) {
{
name: "Empty headers",
headers: map[string]string{},
wantAuthTokMd: TokenMetadata{recievedTokenType: authTokenTypeUnknown},
wantAuthTokMd: TokenMetadata{receivedTokenType: authTokenTypeUnknown},
},
{
name: "Bear token",
headers: map[string]string{"Authorization": fmt.Sprintf("Bearer %s", tokValue)},
wantAuthTokMd: TokenMetadata{
recievedTokenType: authTokenTypeBearer,
receivedTokenType: authTokenTypeBearer,
bearerPayload: tokValue,
UserId: at.GetIamUserId(),
},
@@ -128,7 +136,7 @@ func TestAuthTokenAuthenticator(t *testing.T) {
{Name: jsVisibleCookieName, Value: jsCookieVal},
},
wantAuthTokMd: TokenMetadata{
recievedTokenType: authTokenTypeSplitCookie,
receivedTokenType: authTokenTypeSplitCookie,
httpCookiePayload: httpCookieVal,
jsCookiePayload: jsCookieVal,
UserId: at.GetIamUserId(),
@@ -140,7 +148,7 @@ func TestAuthTokenAuthenticator(t *testing.T) {
{Name: httpOnlyCookieName, Value: httpCookieVal},
},
wantAuthTokMd: TokenMetadata{
recievedTokenType: authTokenTypeUnknown,
receivedTokenType: authTokenTypeUnknown,
httpCookiePayload: httpCookieVal,
},
},
@@ -150,7 +158,7 @@ func TestAuthTokenAuthenticator(t *testing.T) {
{Name: jsVisibleCookieName, Value: jsCookieVal},
},
wantAuthTokMd: TokenMetadata{
recievedTokenType: authTokenTypeUnknown,
receivedTokenType: authTokenTypeUnknown,
jsCookiePayload: jsCookieVal,
},
},
@@ -163,7 +171,7 @@ func TestAuthTokenAuthenticator(t *testing.T) {
},
// We prioritize the auth header over the cookie and if the header is set we ignore the cookies completely.
wantAuthTokMd: TokenMetadata{
recievedTokenType: authTokenTypeBearer,
receivedTokenType: authTokenTypeBearer,
bearerPayload: tokValue,
UserId: at.GetIamUserId(),
},
@@ -176,7 +184,7 @@ func TestAuthTokenAuthenticator(t *testing.T) {
tMD := ToTokenMetadata(ctx)
assert.Equal(t, tc.wantAuthTokMd, tMD)
}}
mux := runtime.NewServeMux(runtime.WithMetadata(TokenAuthenticator(hclog.L(), repoFn)))
mux := runtime.NewServeMux(runtime.WithMetadata(TokenAuthenticator(hclog.L(), tokenRepoFn, iamRepoFn)))
require.NoError(t, services.RegisterOrgServiceHandlerServer(context.Background(), mux, hook))
req := httptest.NewRequest("GET", "http://127.0.0.1/v1/orgs/1", nil)
@@ -12,8 +12,6 @@ import (
"github.com/hashicorp/watchtower/internal/servers/controller/common"
"github.com/hashicorp/watchtower/internal/servers/controller/handlers"
"github.com/hashicorp/watchtower/internal/types/scope"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/wrapperspb"
)
@@ -63,16 +61,6 @@ func (s Service) GetOrg(ctx context.Context, req *pbs.GetOrgRequest) (*pbs.GetOr
return &pbs.GetOrgResponse{Item: o}, nil
}
// Authenticate implements the interface pbs.OrgServiceServer.
func (s Service) Authenticate(ctx context.Context, req *pbs.AuthenticateRequest) (*pbs.AuthenticateResponse, error) {
return nil, status.Error(codes.Unimplemented, "Requested method is unimplemented for Orgs.")
}
// Deauthenticate implements the interface pbs.OrgServiceServer.
func (s Service) Deauthenticate(ctx context.Context, req *pbs.DeauthenticateRequest) (*pbs.DeauthenticateResponse, error) {
return nil, status.Error(codes.Unimplemented, "Requested method is unimplemented for Orgs.")
}
func (s Service) getFromRepo(ctx context.Context, id string) (*pb.Org, error) {
repo, err := s.repo()
if err != nil {
@@ -130,7 +130,7 @@ func (s Service) AddRolePrincipals(ctx context.Context, req *pbs.AddRolePrincipa
if err := validateAddRolePrincipalsRequest(req); err != nil {
return nil, err
}
r, err := s.addPrinciplesInRepo(ctx, req.GetRoleId(), req.GetUserIds(), req.GetGroupIds(), req.GetVersion().GetValue())
r, err := s.addPrinciplesInRepo(ctx, req.GetRoleId(), req.GetPrincipalIds(), req.GetVersion().GetValue())
if err != nil {
return nil, err
}
@@ -144,7 +144,7 @@ func (s Service) SetRolePrincipals(ctx context.Context, req *pbs.SetRolePrincipa
if err := validateSetRolePrincipalsRequest(req); err != nil {
return nil, err
}
r, err := s.setPrinciplesInRepo(ctx, req.GetRoleId(), req.GetUserIds(), req.GetGroupIds(), req.GetVersion().GetValue())
r, err := s.setPrinciplesInRepo(ctx, req.GetRoleId(), req.GetPrincipalIds(), req.GetVersion().GetValue())
if err != nil {
return nil, err
}
@@ -158,7 +158,7 @@ func (s Service) RemoveRolePrincipals(ctx context.Context, req *pbs.RemoveRolePr
if err := validateRemoveRolePrincipalsRequest(req); err != nil {
return nil, err
}
r, err := s.removePrinciplesInRepo(ctx, req.GetRoleId(), req.GetUserIds(), req.GetGroupIds(), req.GetVersion().GetValue())
r, err := s.removePrinciplesInRepo(ctx, req.GetRoleId(), req.GetPrincipalIds(), req.GetVersion().GetValue())
if err != nil {
return nil, err
}
@@ -325,12 +325,12 @@ func (s Service) listFromRepo(ctx context.Context, scopeId string) ([]*pb.Role,
return outRl, nil
}
func (s Service) addPrinciplesInRepo(ctx context.Context, roleId string, userIds []string, groupIds []string, version uint32) (*pb.Role, error) {
func (s Service) addPrinciplesInRepo(ctx context.Context, roleId string, principalIds []string, version uint32) (*pb.Role, error) {
repo, err := s.repoFn()
if err != nil {
return nil, err
}
_, err = repo.AddPrincipalRoles(ctx, roleId, version, userIds, groupIds)
_, err = repo.AddPrincipalRoles(ctx, roleId, version, principalIds)
if err != nil {
return nil, status.Errorf(codes.Internal, "Unable to add principles to role: %v.", err)
}
@@ -344,12 +344,12 @@ func (s Service) addPrinciplesInRepo(ctx context.Context, roleId string, userIds
return toProto(out, pr, roleGrants), nil
}
func (s Service) setPrinciplesInRepo(ctx context.Context, roleId string, userIds []string, groupIds []string, version uint32) (*pb.Role, error) {
func (s Service) setPrinciplesInRepo(ctx context.Context, roleId string, principalIds []string, version uint32) (*pb.Role, error) {
repo, err := s.repoFn()
if err != nil {
return nil, err
}
_, _, err = repo.SetPrincipalRoles(ctx, roleId, version, userIds, groupIds)
_, _, err = repo.SetPrincipalRoles(ctx, roleId, version, principalIds)
if err != nil {
return nil, status.Errorf(codes.Internal, "Unable to set principles on role: %v.", err)
}
@@ -363,12 +363,12 @@ func (s Service) setPrinciplesInRepo(ctx context.Context, roleId string, userIds
return toProto(out, pr, roleGrants), nil
}
func (s Service) removePrinciplesInRepo(ctx context.Context, roleId string, userIds []string, groupIds []string, version uint32) (*pb.Role, error) {
func (s Service) removePrinciplesInRepo(ctx context.Context, roleId string, principalIds []string, version uint32) (*pb.Role, error) {
repo, err := s.repoFn()
if err != nil {
return nil, err
}
_, err = repo.DeletePrincipalRoles(ctx, roleId, version, userIds, groupIds)
_, err = repo.DeletePrincipalRoles(ctx, roleId, version, principalIds)
if err != nil {
return nil, status.Errorf(codes.Internal, "Unable to remove principles from role: %v.", err)
}
@@ -476,12 +476,13 @@ func toProto(in *iam.Role, principals []iam.PrincipalRole, grants []*iam.RoleGra
out.Name = &wrapperspb.StringValue{Value: in.GetName()}
}
for _, p := range principals {
switch p.GetType() {
case iam.UserRoleType.String():
out.UserIds = append(out.UserIds, p.GetPrincipalId())
case iam.GroupRoleType.String():
out.GroupIds = append(out.GroupIds, p.GetPrincipalId())
principal := &pb.Principal{
Id: p.GetPrincipalId(),
Type: p.GetType(),
ScopeId: p.GetPrincipalScopeId(),
}
out.Principals = append(out.Principals, principal)
out.PrincipalIds = append(out.PrincipalIds, p.GetPrincipalId())
}
for _, g := range grants {
out.Grants = append(out.Grants, g.GetRawGrant())
@@ -542,6 +543,9 @@ func validateCreateRequest(req *pbs.CreateRoleRequest) error {
badFields["grant_scope_id"] = "Must be empty or set to the project_id when the scope type is project."
}
}
if item.GetPrincipals() != nil {
badFields["principals"] = "This is a read only field."
}
if len(badFields) > 0 {
return handlers.InvalidArgumentErrorf("Argument errors found in the request.", badFields)
}
@@ -572,6 +576,9 @@ func validateUpdateRequest(req *pbs.UpdateRoleRequest) error {
if item.GetUpdatedTime() != nil {
badFields["updated_time"] = "This is a read only field and cannot be specified in an update request."
}
if item.GetPrincipals() != nil {
badFields["principals"] = "This is a read only field and cannot be specified in an update request."
}
if item.GetGrantScopeId() != nil && req.ProjectId != "" {
if item.GetGrantScopeId().Value != req.ProjectId {
badFields["grant_scope_id"] = "Must be empty or set to the project_id when the scope type is project."
@@ -611,9 +618,8 @@ func validateAddRolePrincipalsRequest(req *pbs.AddRolePrincipalsRequest) error {
if req.GetVersion() == nil {
badFields["version"] = "Required field."
}
if len(req.GetGroupIds()) == 0 && len(req.GetUserIds()) == 0 {
badFields["user_ids"] = "Either user_ids or group_ids must be non empty."
badFields["group_ids"] = "Either user_ids or group_ids must be non empty."
if len(req.GetPrincipalIds()) == 0 {
badFields["principal_ids"] = "Must be non-empty."
}
if len(badFields) > 0 {
return handlers.InvalidArgumentErrorf("Errors in provided fields.", badFields)
@@ -643,9 +649,8 @@ func validateRemoveRolePrincipalsRequest(req *pbs.RemoveRolePrincipalsRequest) e
if req.GetVersion() == nil {
badFields["version"] = "Required field."
}
if len(req.GetGroupIds()) == 0 && len(req.GetUserIds()) == 0 {
badFields["user_ids"] = "Either user_ids or group_ids must be non empty."
badFields["group_ids"] = "Either user_ids or group_ids must be non empty."
if len(req.GetPrincipalIds()) == 0 {
badFields["principal_ids"] = "Must be non-empty."
}
if len(badFields) > 0 {
return handlers.InvalidArgumentErrorf("Errors in provided fields.", badFields)
@@ -662,7 +667,7 @@ func validateAddRoleGrantsRequest(req *pbs.AddRoleGrantsRequest) error {
badFields["version"] = "Required field."
}
if len(req.GetGrants()) == 0 {
badFields["grants"] = "This must be non empty."
badFields["grants"] = "Must be non-empty."
}
if len(badFields) > 0 {
return handlers.InvalidArgumentErrorf("Errors in provided fields.", badFields)
@@ -693,7 +698,7 @@ func validateRemoveRoleGrantsRequest(req *pbs.RemoveRoleGrantsRequest) error {
badFields["version"] = "Required field."
}
if len(req.GetGrants()) == 0 {
badFields["grants"] = "This must be non empty."
badFields["grants"] = "Must be non-empty."
}
if len(badFields) > 0 {
return handlers.InvalidArgumentErrorf("Errors in provided fields.", badFields)
@@ -38,6 +38,30 @@ func createDefaultRolesAndRepo(t *testing.T) (*iam.Role, *iam.Role, func() (*iam
return or, pr, repoFn
}
func equalPrincipals(role *pb.Role, principals []string) bool {
if len(role.Principals) != len(principals) {
return false
}
for _, principal := range principals {
var foundInPrincipals bool
var foundInPrincipalIds bool
for _, v := range role.Principals {
if v.Id == principal {
foundInPrincipals = true
}
}
for _, v := range role.PrincipalIds {
if v == principal {
foundInPrincipalIds = true
}
}
if !foundInPrincipals || !foundInPrincipalIds {
return false
}
}
return true
}
func TestGet(t *testing.T) {
assert := assert.New(t)
require := require.New(t)
@@ -891,11 +915,10 @@ func TestAddPrincipal(t *testing.T) {
role := iam.TestRole(t, conn, scope.GetPublicId())
tc.setup(role)
req := &pbs.AddRolePrincipalsRequest{
OrgId: o.GetPublicId(),
RoleId: role.GetPublicId(),
Version: &wrapperspb.UInt32Value{Value: role.GetVersion()},
UserIds: tc.addUsers,
GroupIds: tc.addGroups,
OrgId: o.GetPublicId(),
RoleId: role.GetPublicId(),
Version: &wrapperspb.UInt32Value{Value: role.GetVersion()},
PrincipalIds: append(tc.addUsers, tc.addGroups...),
}
got, err := s.AddRolePrincipals(context.Background(), req)
@@ -907,8 +930,7 @@ func TestAddPrincipal(t *testing.T) {
require.True(t, ok)
require.NoError(t, err, "Got error: %v", s)
assert.ElementsMatch(t, got.GetItem().GetUserIds(), tc.resultUsers)
assert.ElementsMatch(t, got.GetItem().GetGroupIds(), tc.resultGroups)
assert.True(t, equalPrincipals(got.GetItem(), append(tc.resultUsers, tc.resultGroups...)))
})
}
}
@@ -926,7 +948,6 @@ func TestAddPrincipal(t *testing.T) {
OrgId: "",
ProjectId: role.GetScopeId(),
RoleId: role.GetPublicId(),
GroupIds: []string{},
Version: &wrapperspb.UInt32Value{Value: role.GetVersion()},
},
errCode: codes.InvalidArgument,
@@ -937,7 +958,6 @@ func TestAddPrincipal(t *testing.T) {
OrgId: o.GetPublicId(),
ProjectId: "bad id",
RoleId: role.GetPublicId(),
GroupIds: []string{},
Version: &wrapperspb.UInt32Value{Value: role.GetVersion()},
},
errCode: codes.InvalidArgument,
@@ -948,7 +968,6 @@ func TestAddPrincipal(t *testing.T) {
OrgId: o.GetPublicId(),
ProjectId: role.GetScopeId(),
RoleId: "bad id",
GroupIds: []string{},
Version: &wrapperspb.UInt32Value{Value: role.GetVersion()},
},
errCode: codes.InvalidArgument,
@@ -1039,11 +1058,10 @@ func TestSetPrincipal(t *testing.T) {
role := iam.TestRole(t, conn, scope.GetPublicId())
tc.setup(role)
req := &pbs.SetRolePrincipalsRequest{
OrgId: o.GetPublicId(),
RoleId: role.GetPublicId(),
Version: &wrapperspb.UInt32Value{Value: role.GetVersion()},
UserIds: tc.setUsers,
GroupIds: tc.setGroups,
OrgId: o.GetPublicId(),
RoleId: role.GetPublicId(),
Version: &wrapperspb.UInt32Value{Value: role.GetVersion()},
PrincipalIds: append(tc.setUsers, tc.setGroups...),
}
got, err := s.SetRolePrincipals(context.Background(), req)
@@ -1055,8 +1073,7 @@ func TestSetPrincipal(t *testing.T) {
require.True(t, ok)
require.NoError(t, err, "Got error: %v", s)
assert.Equal(t, got.GetItem().GetUserIds(), tc.resultUsers)
assert.Equal(t, got.GetItem().GetGroupIds(), tc.resultGroups)
assert.True(t, equalPrincipals(got.GetItem(), append(tc.resultUsers, tc.resultGroups...)))
})
}
}
@@ -1074,7 +1091,6 @@ func TestSetPrincipal(t *testing.T) {
OrgId: "",
ProjectId: role.GetScopeId(),
RoleId: role.GetPublicId(),
GroupIds: []string{},
Version: &wrapperspb.UInt32Value{Value: role.GetVersion()},
},
errCode: codes.InvalidArgument,
@@ -1085,7 +1101,6 @@ func TestSetPrincipal(t *testing.T) {
OrgId: o.GetPublicId(),
ProjectId: "bad id",
RoleId: role.GetPublicId(),
GroupIds: []string{},
Version: &wrapperspb.UInt32Value{Value: role.GetVersion()},
},
errCode: codes.InvalidArgument,
@@ -1096,7 +1111,6 @@ func TestSetPrincipal(t *testing.T) {
OrgId: o.GetPublicId(),
ProjectId: role.GetScopeId(),
RoleId: "bad id",
GroupIds: []string{},
Version: &wrapperspb.UInt32Value{Value: role.GetVersion()},
},
errCode: codes.InvalidArgument,
@@ -1205,11 +1219,10 @@ func TestRemovePrincipal(t *testing.T) {
role := iam.TestRole(t, conn, scope.GetPublicId())
tc.setup(role)
req := &pbs.RemoveRolePrincipalsRequest{
OrgId: o.GetPublicId(),
RoleId: role.GetPublicId(),
Version: &wrapperspb.UInt32Value{Value: role.GetVersion()},
UserIds: tc.removeUsers,
GroupIds: tc.removeGroups,
OrgId: o.GetPublicId(),
RoleId: role.GetPublicId(),
Version: &wrapperspb.UInt32Value{Value: role.GetVersion()},
PrincipalIds: append(tc.removeUsers, tc.removeGroups...),
}
got, err := s.RemoveRolePrincipals(context.Background(), req)
@@ -1221,8 +1234,7 @@ func TestRemovePrincipal(t *testing.T) {
require.True(t, ok)
require.NoError(t, err, "Got error: %v", s)
assert.ElementsMatch(t, got.GetItem().GetUserIds(), tc.resultUsers)
assert.ElementsMatch(t, got.GetItem().GetGroupIds(), tc.resultGroups)
assert.True(t, equalPrincipals(got.GetItem(), append(tc.resultUsers, tc.resultGroups...)))
})
}
}
@@ -1240,7 +1252,6 @@ func TestRemovePrincipal(t *testing.T) {
OrgId: "",
ProjectId: role.GetScopeId(),
RoleId: role.GetPublicId(),
GroupIds: []string{},
Version: &wrapperspb.UInt32Value{Value: role.GetVersion()},
},
errCode: codes.InvalidArgument,
@@ -1251,7 +1262,6 @@ func TestRemovePrincipal(t *testing.T) {
OrgId: o.GetPublicId(),
ProjectId: "bad id",
RoleId: role.GetPublicId(),
GroupIds: []string{},
Version: &wrapperspb.UInt32Value{Value: role.GetVersion()},
},
errCode: codes.InvalidArgument,
@@ -1262,7 +1272,6 @@ func TestRemovePrincipal(t *testing.T) {
OrgId: o.GetPublicId(),
ProjectId: role.GetScopeId(),
RoleId: "bad id",
GroupIds: []string{},
Version: &wrapperspb.UInt32Value{Value: role.GetVersion()},
},
errCode: codes.InvalidArgument,
+8 -2
View File
@@ -120,6 +120,11 @@ type TestControllerOpts struct {
// If true, the controller will not be started
DisableAutoStart bool
// DisableAuthorizationFailures will still cause authz checks to be
// performed but they won't cause 403 Forbidden. Useful for API-level
// testing to avoid a lot of faff.
DisableAuthorizationFailures bool
}
func NewTestController(t *testing.T, opts *TestControllerOpts) *TestController {
@@ -183,8 +188,9 @@ func NewTestController(t *testing.T, opts *TestControllerOpts) *TestController {
}
conf := &Config{
RawConfig: opts.Config,
Server: tc.b,
RawConfig: opts.Config,
Server: tc.b,
DisableAuthorizationFailures: opts.DisableAuthorizationFailures,
}
tc.c, err = New(conf)
+1 -4
View File
@@ -1,14 +1,11 @@
package worker
import (
"context"
"github.com/hashicorp/watchtower/internal/cmd/base"
"github.com/hashicorp/watchtower/internal/cmd/config"
)
type Config struct {
*base.Server
RawConfig *config.Config
BaseContext context.Context
RawConfig *config.Config
}
+17 -15
View File
@@ -21,24 +21,25 @@ const (
AddPrincipals Type = 12
SetPrincipals Type = 13
RemovePrincipals Type = 14
Deauthenticate Type = 15
)
var Map = map[string]Type{
"unknown": Unknown,
"list": List,
"create": Create,
"update": Update,
"read": Read,
"delete": Delete,
"authenticate": Authenticate,
"*": All,
"connect": Connect,
"add-grants": AddGrants,
"remove-grants": RemoveGrants,
"set-grants": SetGrants,
"add-principals": AddPrincipals,
"set-principals": SetPrincipals,
"remove-principals": RemovePrincipals,
Create.String(): Create,
List.String(): List,
Update.String(): Update,
Read.String(): Read,
Delete.String(): Delete,
Authenticate.String(): Authenticate,
All.String(): All,
Connect.String(): Connect,
AddGrants.String(): AddGrants,
RemoveGrants.String(): RemoveGrants,
SetGrants.String(): SetGrants,
AddPrincipals.String(): AddPrincipals,
SetPrincipals.String(): SetPrincipals,
RemovePrincipals.String(): RemovePrincipals,
Deauthenticate.String(): Deauthenticate,
}
func (a Type) String() string {
@@ -58,5 +59,6 @@ func (a Type) String() string {
"add-principals",
"set-principals",
"remove-principals",
"deauthenticate",
}[a]
}
+4
View File
@@ -71,6 +71,10 @@ func TestAction(t *testing.T) {
action: SetPrincipals,
want: "set-principals",
},
{
action: Deauthenticate,
want: "deauthenticate",
},
}
for _, tt := range tests {
t.Run(tt.want, func(t *testing.T) {
+25 -43
View File
@@ -24,6 +24,9 @@ const (
Host Type = 17
Target Type = 18
Global Type = 19
// TODO: remove this after demo
Group Type = 20
)
func (r Type) String() string {
@@ -48,50 +51,29 @@ func (r Type) String() string {
"host",
"target",
"global",
"group",
}[r]
}
func StringToResourceType(s string) Type {
switch s {
case Scope.String():
return Scope
case User.String():
return User
case StaticGroup.String():
return StaticGroup
case Role.String():
return Role
case Org.String():
return Org
case StaticGroupMember.String():
return StaticGroupMember
case StaticGroupUserMember.String():
return StaticGroupUserMember
case AssignedRole.String():
return AssignedRole
case AssignedUserRole.String():
return AssignedUserRole
case AssignedStaticGroupRole.String():
return AssignedStaticGroupRole
case RoleGrant.String():
return RoleGrant
case AuthMethod.String():
return AuthMethod
case Project.String():
return Project
case All.String():
return All
case HostCatalog.String():
return HostCatalog
case HostSet.String():
return HostSet
case Host.String():
return Host
case Target.String():
return Target
case Global.String():
return Global
default:
return Unknown
}
var Map = map[string]Type{
Scope.String(): Scope,
User.String(): User,
StaticGroup.String(): StaticGroup,
Role.String(): Role,
Org.String(): Org,
StaticGroupMember.String(): StaticGroupMember,
StaticGroupUserMember.String(): StaticGroupUserMember,
AssignedRole.String(): AssignedRole,
AssignedUserRole.String(): AssignedUserRole,
AssignedStaticGroupRole.String(): AssignedStaticGroupRole,
RoleGrant.String(): RoleGrant,
AuthMethod.String(): AuthMethod,
Project.String(): Project,
All.String(): All,
HostCatalog.String(): HostCatalog,
HostSet.String(): HostSet,
Host.String(): Host,
Target.String(): Target,
Global.String(): Global,
Group.String(): Group,
}
+1 -1
View File
@@ -95,7 +95,7 @@ func Test_Resource(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.typeString, func(t *testing.T) {
assert.Equalf(t, tt.want, StringToResourceType(tt.typeString), "unexpected type for %s", tt.typeString)
assert.Equalf(t, tt.want, Map[tt.typeString], "unexpected type for %s", tt.typeString)
assert.Equalf(t, tt.typeString, tt.want.String(), "unexpected string for %s", tt.typeString)
})
}
+4 -11
View File
@@ -28,15 +28,8 @@ func (s Type) Prefix() string {
}[s]
}
func StringToScopeType(s string) Type {
switch s {
case Global.String():
return Global
case Org.String():
return Org
case Project.String():
return Project
default:
return Unknown
}
var Map = map[string]Type{
Global.String(): Global,
Org.String(): Org,
Project.String(): Project,
}
+2 -2
View File
@@ -6,7 +6,7 @@ import (
"github.com/stretchr/testify/assert"
)
func Test_StringToScopeType(t *testing.T) {
func Test_Map(t *testing.T) {
tests := []struct {
name string
s string
@@ -41,7 +41,7 @@ func Test_StringToScopeType(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert := assert.New(t)
got := StringToScopeType(tt.s)
got := Map[tt.s]
assert.Equal(tt.want, got)
assert.Equalf(tt.wantPrefix, got.Prefix(), "unexpected prefix for %s", tt.s)
})