forked from TrueCloudLab/frostfs-s3-gw
184 lines
4.3 KiB
Go
184 lines
4.3 KiB
Go
package client
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
policycontract "git.frostfs.info/TrueCloudLab/frostfs-contract/policy"
|
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/pkg/service/control"
|
|
controlSvc "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/pkg/service/control/server"
|
|
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
|
"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
|
|
}
|
|
|
|
type PolicyData struct {
|
|
Kind policycontract.Kind
|
|
Name string
|
|
Chain *chain.Chain
|
|
}
|
|
|
|
type PolicyInfo struct {
|
|
Kind policycontract.Kind
|
|
Name string
|
|
ChainID chain.ID
|
|
}
|
|
|
|
func kindToTarget(k policycontract.Kind) control.PolicyTarget {
|
|
switch k {
|
|
case policycontract.Container:
|
|
return control.PolicyTarget_CONTAINER
|
|
case policycontract.Namespace:
|
|
return control.PolicyTarget_NAMESPACE
|
|
case 'u':
|
|
return control.PolicyTarget_USER
|
|
case 'g':
|
|
return control.PolicyTarget_GROUP
|
|
default:
|
|
return control.PolicyTarget_TARGET_UNDEFINED
|
|
}
|
|
}
|
|
|
|
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)
|
|
|
|
cli := &Client{
|
|
svc: svc,
|
|
key: key,
|
|
}
|
|
|
|
return cli, cli.Healthcheck(ctx)
|
|
}
|
|
|
|
func (c *Client) Healthcheck(ctx context.Context) error {
|
|
req := &control.HealthCheckRequest{}
|
|
if err := controlSvc.SignMessage(&c.key.PrivateKey, req); err != nil {
|
|
return err
|
|
}
|
|
|
|
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) PutPolicies(ctx context.Context, policies []PolicyData) error {
|
|
chainDatas := make([]*control.PutPoliciesRequest_ChainData, len(policies))
|
|
for i := range policies {
|
|
chainDatas[i] = &control.PutPoliciesRequest_ChainData{
|
|
Target: kindToTarget(policies[i].Kind),
|
|
Name: policies[i].Name,
|
|
Chain: policies[i].Chain.Bytes(),
|
|
}
|
|
}
|
|
|
|
req := &control.PutPoliciesRequest{
|
|
Body: &control.PutPoliciesRequest_Body{
|
|
ChainDatas: chainDatas,
|
|
},
|
|
}
|
|
|
|
if err := controlSvc.SignMessage(&c.key.PrivateKey, req); err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err := c.svc.PutPolicies(ctx, req)
|
|
return err
|
|
}
|
|
|
|
func (c *Client) RemovePolicies(ctx context.Context, policies []PolicyInfo) error {
|
|
chainInfos := make([]*control.RemovePoliciesRequest_ChainInfo, len(policies))
|
|
for i := range policies {
|
|
chainInfos[i] = &control.RemovePoliciesRequest_ChainInfo{
|
|
Target: kindToTarget(policies[i].Kind),
|
|
Name: policies[i].Name,
|
|
ChainID: []byte(policies[i].ChainID),
|
|
}
|
|
}
|
|
|
|
req := &control.RemovePoliciesRequest{
|
|
Body: &control.RemovePoliciesRequest_Body{
|
|
ChainInfos: chainInfos,
|
|
},
|
|
}
|
|
|
|
if err := controlSvc.SignMessage(&c.key.PrivateKey, req); err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err := c.svc.RemovePolicies(ctx, req)
|
|
return err
|
|
}
|
|
|
|
func (c *Client) GetPolicy(ctx context.Context, kind policycontract.Kind, name string, chainID chain.ID) (*chain.Chain, error) {
|
|
req := &control.GetPolicyRequest{
|
|
Body: &control.GetPolicyRequest_Body{
|
|
Target: kindToTarget(kind),
|
|
Name: name,
|
|
ChainID: []byte(chainID),
|
|
},
|
|
}
|
|
|
|
if err := controlSvc.SignMessage(&c.key.PrivateKey, req); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
resp, err := c.svc.GetPolicy(ctx, req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var policyChain chain.Chain
|
|
if err = policyChain.DecodeBytes(resp.GetBody().GetChain()); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &policyChain, nil
|
|
}
|
|
|
|
func (c *Client) ListPolicies(ctx context.Context, kind policycontract.Kind, name string) ([]chain.ID, error) {
|
|
req := &control.ListPoliciesRequest{
|
|
Body: &control.ListPoliciesRequest_Body{
|
|
Target: kindToTarget(kind),
|
|
Name: name,
|
|
},
|
|
}
|
|
|
|
if err := controlSvc.SignMessage(&c.key.PrivateKey, req); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
resp, err := c.svc.ListPolicies(ctx, req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
res := make([]chain.ID, len(resp.GetBody().GetChainIDs()))
|
|
for i, chainID := range resp.GetBody().GetChainIDs() {
|
|
res[i] = chain.ID(chainID)
|
|
}
|
|
|
|
return res, nil
|
|
}
|