Last active
October 22, 2020 22:22
-
-
Save derekperkins/cde013ec90b8f5cd3777c0ac3df91ffb to your computer and use it in GitHub Desktop.
Nozzle cloudidentity code
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package internal | |
import ( | |
"context" | |
"strconv" | |
"go.nozzle.io/namespaces/iam/iamapi" | |
iampb "go.nozzle.io/namespaces/iam/iamapi/iamapipb" | |
"go.nozzle.io/namespaces/workspaces/eventorapi/eventorpb" | |
"go.nozzle.io/namespaces/workspaces/workspacesapi" | |
"go.nozzle.io/namespaces/workspaces/workspacesapi/workspacespb" | |
"go.nozzle.io/pkg/cloudidentity" | |
"go.nozzle.io/pkg/e" | |
"go.nozzle.io/pkg/ngrpc" | |
"go.nozzle.io/pkg/workers" | |
) | |
// App holds the state and performs the business logic. | |
type App struct { | |
iamClient iamapi.IAMAPI | |
adminClient *cloudidentity.Client | |
workspaceClient workspacesapi.API | |
} | |
// Work performs the business logic. | |
func (a *App) Work(c context.Context, msg *workers.Message) { | |
// parse message | |
var event eventorpb.Event | |
err := ngrpc.JSONUnmarshal(msg.Data, &event) | |
if err != nil { | |
msg.Err = e.Wrap(err) | |
return | |
} | |
// filter out unwanted kinds until we get filtering in topics | |
if !(event.Kind == workspacespb.WorkspaceKind && event.Type == eventorpb.Event_TYPE_CREATE) { | |
return | |
} | |
// retrieve the workspace | |
ws, err := a.workspaceClient.GetWorkspaceByID(c, event.KindId) | |
if err != nil { | |
msg.Err = e.Wrap(err) | |
return | |
} | |
// Process event message | |
err = a.work(c, ws) | |
if err != nil { | |
msg.Err = err | |
} | |
} | |
func (a *App) work(c context.Context, ws *workspacespb.Workspace) error { | |
// create a google group for the workspace | |
groupID, err := a.adminClient.UpsertGroup(c, ws.Slug, strconv.FormatInt(ws.Id, 10), "A workspace group for managing BigQuery permissions") | |
if err != nil { | |
return e.Wrap(err, e.With("workspace_id", ws.Id)) | |
} | |
// add all users in the workspace to the group | |
users, err := a.iamClient.ListUsers(c, &iampb.ListUsersRequest{ | |
WorkspaceId: ws.Id, | |
}) | |
if err != nil { | |
return e.Wrap(err) | |
} | |
// add users to the group | |
for _, user := range users { | |
err = a.adminClient.UpsertMember(c, groupID, user.Name, user.Email, cloudidentity.RoleMember) | |
if err != nil { | |
// report the error but try the other users | |
e.Wrap(err, e.With("user_id", user.Id)).Report(c) | |
} | |
} | |
return nil | |
} | |
// NewApp creates an instance of the application. | |
func NewApp(c context.Context, adminClient *cloudidentity.Client, iamClient iamapi.IAMAPI, workspaceClient workspacesapi.API) (*App, error) { | |
return &App{ | |
adminClient: adminClient, | |
iamClient: iamClient, | |
workspaceClient: workspaceClient, | |
}, nil | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package cloudidentity | |
import ( | |
"context" | |
"net/http" | |
"google.golang.org/api/cloudidentity/v1" | |
"google.golang.org/api/googleapi" | |
) | |
// MemberRole is a members role. | |
type MemberRole string | |
var ( | |
// RoleManager This role is only available if the | |
// Google Groups for Business is enabled using the Admin console. | |
// A MANAGER role can do everything done by an OWNER role except | |
// make a member an OWNER or delete the group. A group can have multiple MANAGER members. | |
RoleManager MemberRole = "MANAGER" | |
// RoleMember his role can subscribe to a group, | |
// view discussion archives, and view the group's membership list. | |
RoleMember MemberRole = "MEMBER" | |
// RoleOwner This role can send messages to the group, | |
// add or remove members, change member roles, change group's settings, | |
// and delete the group. An OWNER must be a member of the group. | |
// A group can have more than one OWNER. | |
RoleOwner MemberRole = "OWNER" | |
) | |
const groupParent = "customers/C03sdo746" | |
// NewClient will return a new instance of the admin client. | |
func NewClient(c context.Context) (*Client, error) { | |
client, err := cloudidentity.NewService(c) | |
if err != nil { | |
return nil, err | |
} | |
return &Client{ | |
identityClient: client, | |
}, nil | |
} | |
// Client is used to manage google Admin settings. | |
type Client struct { | |
identityClient *cloudidentity.Service | |
} | |
// UpsertGroup create or update a group. | |
func (cl *Client) UpsertGroup(c context.Context, wsSlug, workspaceID, description string) (string, error) { | |
log.Debug(c, "upserting group "+wsSlug) | |
// check if exists before creating | |
resp, err := cl.identityClient.Groups.Lookup().GroupKeyId("workspaces-" + wsSlug + "@nozzle.app").Do() | |
if err != nil { | |
if gErr, ok := err.(*googleapi.Error); ok { | |
// group already exists ignore | |
if gErr.Code == http.StatusNotFound { | |
name, err := cl.createGroup(c, workspaceID, description) | |
if err != nil { | |
return "", err | |
} | |
return name, nil | |
} | |
} | |
return "", err | |
} | |
log.Debug(c, "upsert for group "+wsSlug+" successful") | |
return resp.Name, nil | |
} | |
func (cl *Client) createGroup(c context.Context, wsSlug string, description string) (string, error) { | |
resp, err := cl.identityClient.Groups.Create(&cloudidentity.Group{ | |
GroupKey: &cloudidentity.EntityKey{ | |
Id: "workspaces-" + wsSlug + "@nozzle.app", | |
}, | |
DisplayName: wsSlug, | |
Description: description, | |
Parent: groupParent, | |
Labels: map[string]string{ | |
"cloudidentity.googleapis.com/discussion_forums": "", | |
}, | |
}).Do() | |
if err != nil { | |
return "", err | |
} | |
return resp.Name, nil | |
} | |
// UpsertMember will create a member for a group or update it. | |
func (cl *Client) UpsertMember(c context.Context, groupKey, name, email string, role MemberRole) error { | |
log.Debug(c, "upsert member for "+email) | |
_, err := cl.identityClient.Groups.Memberships.Create("groups/"+groupKey, &cloudidentity.Membership{ | |
Name: name, | |
PreferredMemberKey: &cloudidentity.EntityKey{ | |
Id: email, | |
}, | |
Roles: []*cloudidentity.MembershipRole{{ | |
Name: string(role), | |
}}, | |
}).Do() | |
if err != nil { | |
if gErr, ok := err.(*googleapi.Error); ok { | |
// group already exists ignore | |
if gErr.Code == http.StatusConflict { | |
return nil | |
} | |
} | |
return err | |
} | |
log.Debug(c, "upsert member for "+email+" success") | |
return nil | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module go.nozzle.io | |
go 1.15 | |
require ( | |
cloud.google.com/go v0.67.0 | |
cloud.google.com/go/bigquery v1.11.2 | |
cloud.google.com/go/firestore v1.3.0 // indirect | |
// Don't upgrade this until there is a fix for etcd and grpc | |
cloud.google.com/go/logging v1.0.0 | |
cloud.google.com/go/pubsub v1.8.0 | |
cloud.google.com/go/storage v1.12.0 | |
contrib.go.opencensus.io/exporter/prometheus v0.2.0 | |
contrib.go.opencensus.io/exporter/stackdriver v0.13.4 | |
contrib.go.opencensus.io/integrations/ocsql v0.1.6 | |
firebase.google.com/go v3.13.0+incompatible | |
github.com/DATA-DOG/go-sqlmock v1.5.0 | |
// There is an issue with upgrading this do to their use of the kubernetes api | |
github.com/argoproj/argo-rollouts v0.7.2 | |
github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054 // indirect | |
github.com/cloudflare/cloudflare-go v0.13.3 | |
// Becareful upgrading | |
github.com/coreos/prometheus-operator v0.38.0 | |
github.com/davecgh/go-spew v1.1.1 | |
github.com/dgrijalva/jwt-go v3.2.0+incompatible | |
// Some tests need this to remain pinned to this version | |
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 | |
github.com/dimfeld/httptreemux v5.0.1+incompatible | |
github.com/dustin/go-humanize v1.0.0 | |
github.com/getsentry/raven-go v0.2.0 | |
github.com/ghodss/yaml v1.0.0 | |
github.com/go-chi/chi v4.1.2+incompatible | |
// Pinned to v0.1.0 for now because of breaking api change that affects zapr | |
github.com/go-logr/logr v0.1.0 | |
github.com/go-openapi/swag v0.19.9 // indirect | |
github.com/go-sql-driver/mysql v1.5.0 | |
github.com/golang/geo v0.0.0-20200730024412-e86565bf3f35 | |
github.com/golang/protobuf v1.4.2 | |
github.com/google/go-github v17.0.0+incompatible | |
github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75 | |
// Upgrading may be an inssue | |
github.com/grpc-ecosystem/grpc-gateway v1.12.1 | |
github.com/hashicorp/go-rootcerts v1.0.2 // indirect | |
github.com/josephbergevin/strcase v0.0.0-20180315164216-78ac914e4242 | |
github.com/json-iterator/go v1.1.10 | |
github.com/klauspost/compress v1.11.0 // indirect | |
github.com/klauspost/pgzip v1.2.5 // indirect | |
github.com/mitchellh/hashstructure v1.0.0 | |
github.com/ngrok/sqlmw v0.0.0-20200129213757-d5c93a81bec6 | |
github.com/nozzle/fetcher v0.0.0-20200602204932-612c04bfcd4c | |
github.com/nozzle/throttler v0.0.0-20180817012639-2ea982251481 | |
github.com/olekukonko/tablewriter v0.0.4 | |
github.com/onsi/ginkgo v1.14.1 | |
github.com/onsi/gomega v1.10.2 | |
github.com/patrickmn/go-cache v0.0.0-20180527043350-9f6ff22cfff8 | |
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4 | |
github.com/pkg/errors v0.9.1 | |
github.com/prometheus/client_golang v1.7.1 // indirect | |
github.com/pusher/pusher-http-go v4.0.1+incompatible | |
github.com/renstrom/shortuuid v3.0.0+incompatible | |
github.com/robfig/cron v1.2.0 | |
github.com/sanity-io/litter v1.3.0 | |
github.com/satori/go.uuid v1.2.0 | |
github.com/sendgrid/rest v2.6.1+incompatible // indirect | |
github.com/sendgrid/sendgrid-go v3.6.4+incompatible | |
github.com/sergi/go-diff v1.1.0 | |
github.com/spf13/cobra v1.0.0 | |
github.com/spf13/pflag v1.0.5 | |
github.com/stretchr/testify v1.6.1 | |
github.com/stripe/stripe-go v70.15.0+incompatible | |
github.com/stripe/stripe-go/v71 v71.48.0 | |
github.com/teambition/rrule-go v1.6.0 | |
github.com/testcontainers/testcontainers-go v0.9.0 | |
github.com/ugorji/go/codec v1.1.9 | |
go.opencensus.io v0.22.4 | |
golang.org/x/crypto v0.0.0-20200930160638-afb6bcd081ae | |
golang.org/x/net v0.0.0-20200930145003-4acb6c075d10 | |
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43 | |
golang.org/x/text v0.3.3 | |
google.golang.org/api v0.32.0 | |
google.golang.org/appengine v1.6.6 | |
google.golang.org/genproto v0.0.0-20201001141541-efaab9d3c4f7 | |
google.golang.org/grpc v1.32.0 | |
gopkg.in/fatih/set.v0 v0.2.1 | |
gopkg.in/yaml.v2 v2.3.0 | |
// Upgrading may be an issue | |
k8s.io/api v0.18.6 | |
// Upgrading may be an issue | |
k8s.io/apimachinery v0.18.6 | |
k8s.io/client-go v12.0.0+incompatible | |
sigs.k8s.io/controller-runtime v0.6.0 | |
// Upgrading may be an issue | |
vitess.io/vitess v0.0.0-20200225161936-ad4e47a2dbcd | |
) | |
replace github.com/hashicorp/consul => github.com/hashicorp/consul v1.5.0 | |
replace k8s.io/client-go => k8s.io/client-go v0.18.2 | |
replace cloud.google.com/go/logging => cloud.google.com/go/logging v1.1.0 | |
replace google.golang.org/grpc => google.golang.org/grpc v1.29.1 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment