package client import ( "context" "encoding/json" "fmt" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/pkg/service/control" controlSvc "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/pkg/service/control/server" policyengine "git.frostfs.info/TrueCloudLab/policy-engine" engineiam "git.frostfs.info/TrueCloudLab/policy-engine/iam" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "go.uber.org/zap" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" ) type Client struct { svc control.ControlServiceClient key *keys.PrivateKey } type Config struct { Logger *zap.Logger } func New(ctx context.Context, addr string, key *keys.PrivateKey) (*Client, error) { conn, err := grpc.Dial(addr, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { return nil, fmt.Errorf("failed to dial s3 gw control api: %w", err) } svc := control.NewControlServiceClient(conn) // todo consider add invoking healthcheck // c.Healthcheck(ctx) return &Client{ svc: svc, key: key, }, nil } func (c *Client) Healthcheck(ctx context.Context) error { req := &control.HealthCheckRequest{} sig, err := controlSvc.SignMessage(&c.key.PrivateKey, req.Body) if err != nil { return err } req.Signature = sig res, err := c.svc.HealthCheck(ctx, req) if err != nil { return err } if res.Body.HealthStatus != control.HealthStatus_READY { return fmt.Errorf("service isn't ready, status: %s", res.Body.HealthStatus) } return nil } func (c *Client) AddPolicyIAM(ctx context.Context, policy string) error { var p engineiam.Policy if err := json.Unmarshal([]byte(policy), &p); err != nil { return err } chain, err := p.ToChain() if err != nil { return err } return c.AddPolicy(ctx, chain) } func (c *Client) AddPolicy(ctx context.Context, chain *policyengine.Chain) error { req := &control.AddPolicyRequest{ Body: chain.Bytes(), } sig, err := controlSvc.SignMessage(&c.key.PrivateKey, req.Body) if err != nil { return err } req.Signature = sig _, err = c.svc.AddPolicy(ctx, req) return err }