Skip to content

Commit

Permalink
feat: add shield extractor
Browse files Browse the repository at this point in the history
  • Loading branch information
scortier committed May 30, 2022
1 parent 6f13cc1 commit d64b801
Show file tree
Hide file tree
Showing 8 changed files with 1,104 additions and 60 deletions.
31 changes: 13 additions & 18 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,19 @@ require (
cloud.google.com/go/bigquery v1.8.0
cloud.google.com/go/bigtable v1.10.1
cloud.google.com/go/logging v1.4.2
cloud.google.com/go/storage v1.16.1
cloud.google.com/go/storage v1.18.2
github.com/AlecAivazis/survey/v2 v2.3.2
github.com/ClickHouse/clickhouse-go v1.4.5
github.com/MakeNowJust/heredoc v1.0.0
github.com/Microsoft/go-winio v0.5.0 // indirect
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38
github.com/aws/aws-sdk-go v1.40.34
github.com/aws/aws-sdk-go v1.40.53
github.com/blastrain/vitess-sqlparser v0.0.0-20201030050434-a139afbb1aba
github.com/cenkalti/backoff/v4 v4.1.1
github.com/containerd/continuity v0.1.0 // indirect
github.com/denisenkom/go-mssqldb v0.10.0
github.com/dnaeon/go-vcr/v2 v2.0.1
github.com/elastic/go-elasticsearch v0.0.0
github.com/elastic/go-elasticsearch/v8 v8.0.0-20210708134649-33f644c8e327
github.com/etsy/statsd v0.9.0
github.com/fatih/color v1.10.0 // indirect
github.com/flimzy/diff v0.1.7 // indirect
github.com/flimzy/testy v0.1.17 // indirect
github.com/go-kivik/couchdb v2.0.0+incompatible
Expand All @@ -37,16 +34,15 @@ require (
github.com/hashicorp/go-hclog v0.16.1
github.com/hashicorp/go-plugin v1.4.2
github.com/kr/text v0.2.0 // indirect
github.com/lib/pq v1.10.2
github.com/lib/pq v1.10.4
github.com/mcuadros/go-defaults v1.2.0
github.com/mitchellh/mapstructure v1.4.1
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
github.com/mitchellh/mapstructure v1.4.2
github.com/muesli/reflow v0.3.0 // indirect
github.com/nsf/jsondiff v0.0.0-20210926074059-1e845ec5d249
github.com/odpf/optimus v0.2.1-rc.1
github.com/odpf/salt v0.0.0-20220123093403-faac19525416
github.com/opencontainers/runc v1.0.1 // indirect
github.com/ory/dockertest/v3 v3.7.0
github.com/odpf/shield v0.2.3
github.com/ory/dockertest/v3 v3.8.0
github.com/pierrec/lz4 v2.6.1+incompatible // indirect
github.com/pkg/errors v0.9.1
github.com/prestodb/presto-go-client v0.0.0-20211201125635-ad28cec17d6c
Expand All @@ -55,16 +51,15 @@ require (
github.com/sijms/go-ora/v2 v2.2.22
github.com/snowflakedb/gosnowflake v1.6.7
github.com/spf13/cobra v1.2.1
github.com/spf13/viper v1.8.1
github.com/spf13/viper v1.9.0
github.com/stretchr/testify v1.7.0
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
gitlab.com/flimzy/testy v0.8.0 // indirect
go.mongodb.org/mongo-driver v1.5.3
go.mongodb.org/mongo-driver v1.7.0
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.25.0
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f
google.golang.org/api v0.56.0
google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83
google.golang.org/grpc v1.40.0
google.golang.org/protobuf v1.27.1
golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1
google.golang.org/api v0.58.0
google.golang.org/genproto v0.0.0-20211020151524-b7c3a969101a
google.golang.org/grpc v1.41.0
google.golang.org/protobuf v1.28.0
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
)
661 changes: 620 additions & 41 deletions go.sum

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion plugins/extractors/populate.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ import (
_ "github.com/odpf/meteor/plugins/extractors/optimus"
_ "github.com/odpf/meteor/plugins/extractors/oracle"
_ "github.com/odpf/meteor/plugins/extractors/postgres"
_ "github.com/odpf/meteor/plugins/extractors/redshift"
_ "github.com/odpf/meteor/plugins/extractors/presto"
_ "github.com/odpf/meteor/plugins/extractors/redshift"
_ "github.com/odpf/meteor/plugins/extractors/shield"
_ "github.com/odpf/meteor/plugins/extractors/snowflake"
_ "github.com/odpf/meteor/plugins/extractors/superset"
_ "github.com/odpf/meteor/plugins/extractors/tableau"
Expand Down
Empty file.
80 changes: 80 additions & 0 deletions plugins/extractors/shield/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package shield

import (
"context"
"fmt"
grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
grpc_retry "github.com/grpc-ecosystem/go-grpc-middleware/retry"
grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
sh "github.com/odpf/shield/proto/v1beta1"
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
"google.golang.org/grpc"
"time"
)

const (
service = "shield"
GRPCMaxClientSendSize = 45 << 20 // 45MB
GRPCMaxClientRecvSize = 45 << 20 // 45MB
GRPCMaxRetry uint = 3
)

type Client interface {
sh.ShieldServiceClient
Connect(ctx context.Context, host string) error
Close() error
}

func newClient() Client {
return &client{}
}

type client struct {
sh.ShieldServiceClient
conn *grpc.ClientConn
}

func (c *client) Connect(ctx context.Context, host string) (err error) {
dialTimeoutCtx, dialCancel := context.WithTimeout(ctx, time.Second*2)
defer dialCancel()

if c.conn, err = c.createConnection(dialTimeoutCtx, host); err != nil {
err = fmt.Errorf("error creating connection: %w", err)
return
}

c.ShieldServiceClient = sh.NewShieldServiceClient(c.conn)

return
}

func (c *client) Close() error {
return c.conn.Close()
}

func (c *client) createConnection(ctx context.Context, host string) (*grpc.ClientConn, error) {
retryOpts := []grpc_retry.CallOption{
grpc_retry.WithBackoff(grpc_retry.BackoffExponential(100 * time.Millisecond)),
grpc_retry.WithMax(GRPCMaxRetry),
}
var opts []grpc.DialOption
opts = append(opts,
grpc.WithInsecure(),
grpc.WithBlock(),
grpc.WithDefaultCallOptions(
grpc.MaxCallSendMsgSize(GRPCMaxClientSendSize),
grpc.MaxCallRecvMsgSize(GRPCMaxClientRecvSize),
),
grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
grpc_retry.UnaryClientInterceptor(retryOpts...),
otelgrpc.UnaryClientInterceptor(),
grpc_prometheus.UnaryClientInterceptor,
)),
grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
otelgrpc.StreamClientInterceptor(),
grpc_prometheus.StreamClientInterceptor,
)),
)

return grpc.DialContext(ctx, host, opts...)
}
132 changes: 132 additions & 0 deletions plugins/extractors/shield/shield.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package shield

import (
"context"
_ "embed" // used to print the embedded assets
"fmt"
"github.com/odpf/meteor/models"
commonv1beta1 "github.com/odpf/meteor/models/odpf/assets/common/v1beta1"
assetsv1beta1 "github.com/odpf/meteor/models/odpf/assets/v1beta1"
"github.com/odpf/meteor/plugins"
"github.com/odpf/meteor/registry"
"github.com/odpf/meteor/utils"
"github.com/odpf/salt/log"
sh "github.com/odpf/shield/proto/v1beta1"
)

//go:embed README.md
var summary string

// Config holds the set of configuration for the shield extractor
type Config struct {
Host string `mapstructure:"host" validate:"required"`
}

var sampleConfig = `
host: shield.com:80`

// Extractor manages the communication with the shield service
type Extractor struct {
logger log.Logger
config Config
client Client
}

func New(logger log.Logger, client Client) *Extractor {
return &Extractor{
logger: logger,
client: client,
}
}

// Info returns the detailed information about the extractor
func (e *Extractor) Info() plugins.Info {
return plugins.Info{
Description: "Shield' users metadata",
SampleConfig: sampleConfig,
Summary: summary,
Tags: []string{"shield", "extractor"},
}
}

// Validate validates the configuration of the extractor
func (e *Extractor) Validate(configMap map[string]interface{}) (err error) {
return utils.BuildConfig(configMap, &Config{})
}

// Init initializes the extractor
func (e *Extractor) Init(ctx context.Context, configMap map[string]interface{}) (err error) {
if err := utils.BuildConfig(configMap, &e.config); err != nil {
return plugins.InvalidConfigError{}
}

if err := e.client.Connect(ctx, e.config.Host); err != nil {
return fmt.Errorf("error connecting to host: %w", err)
}

return
}

// Extract extracts the user information
func (e *Extractor) Extract(ctx context.Context, emit plugins.Emit) error {
defer e.client.Close()

listUsers, err := e.client.ListUsers(ctx, &sh.ListUsersRequest{
Fields: nil,
})
if err != nil {
return fmt.Errorf("error fetching users: %w", err)
}

for _, user := range listUsers.Users {
role, roleErr := e.client.GetRole(ctx, &sh.GetRoleRequest{Id: user.GetId()})
if roleErr != nil {
return fmt.Errorf("error fetching user roles: %w", err)
}

grp, grpErr := e.client.GetGroup(ctx, &sh.GetGroupRequest{Id: user.GetId()})
if grpErr != nil {
return fmt.Errorf("error fetching user groups: %w", err)
}

emit(models.NewRecord(&assetsv1beta1.User{
Resource: &commonv1beta1.Resource{
Urn: fmt.Sprintf("%s::%s/%s", service, e.config.Host, user.GetId()),
Name: user.GetName(),
Service: service,
Type: "user",
Description: user.GetSlug(),
},
Email: user.GetEmail(),
Username: user.GetId(),
FullName: user.GetName(),
DisplayName: "",
Title: "",
Status: "active",
ManagerEmail: "",
Profiles: nil,
Memberships: []*assetsv1beta1.Membership{
{
GroupUrn: fmt.Sprintf("%s:%s", grp.Group.GetName(), grp.Group.GetId()),
Role: []string{role.Role.GetName()},
},
},
Timestamps: &commonv1beta1.Timestamp{
CreateTime: user.GetCreatedAt(),
UpdateTime: user.GetUpdatedAt(),
},
Event: nil,
}))
}

return nil
}

// Register the extractor to catalog
func init() {
if err := registry.Extractors.Register("shield", func() plugins.Extractor {
return New(plugins.GetLog(), newClient())
}); err != nil {
panic(err)
}
}
Loading

0 comments on commit d64b801

Please sign in to comment.