Skip to content

Commit

Permalink
feat: updated shield provider to support new shield version
Browse files Browse the repository at this point in the history
  • Loading branch information
utsav14nov committed Sep 24, 2024
1 parent 50feb29 commit afbdc45
Show file tree
Hide file tree
Showing 8 changed files with 153 additions and 152 deletions.
2 changes: 1 addition & 1 deletion domain/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ type AppealConfig struct {
AllowActiveAccessExtensionIn string `json:"allow_active_access_extension_in" yaml:"allow_active_access_extension_in" validate:"required"`
}
type ProviderConfig struct {
Type string `json:"type" yaml:"type" validate:"required,oneof=google_bigquery metabase grafana tableau gcloud_iam noop gcs"`
Type string `json:"type" yaml:"type" validate:"required,oneof=google_bigquery metabase grafana tableau gcloud_iam noop gcs shield"`
URN string `json:"urn" yaml:"urn" validate:"required"`
AllowedAccountTypes []string `json:"allowed_account_types" yaml:"allowed_account_types" validate:"omitempty,min=1"`
Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"`
Expand Down
18 changes: 9 additions & 9 deletions mocks/ShieldClient.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

226 changes: 103 additions & 123 deletions plugins/providers/shield/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,30 @@ const (
projectsEndpoint = "/admin/v1beta1/projects"
organizationEndpoint = "/admin/v1beta1/organizations"
selfUserEndpoint = "admin/v1beta1/users/self"
relationsEndpoint = "/admin/v1beta1/relations"
objectEndpoint = "/admin/v1beta1/object"

groupsConst = "groups"
projectsConst = "projects"
organizationsConst = "organizations"
usersConst = "users"
userConst = "user"
relationsConst = "relations"
relationConst = "relation"

userNamespaceConst = "shield/user"
groupNamespaceConst = "shield/group"
projectNamespaceConst = "shield/project"
organizationNamespaceConst = "shield/organization"
managerRoleConst = "manager"
)

type successAccess interface{}

type ShieldClient interface {
GetTeams(ctx context.Context) ([]*Team, error)
GetTeams(ctx context.Context) ([]*Group, error)
GetProjects(ctx context.Context) ([]*Project, error)
GetOrganizations(ctx context.Context) ([]*Organization, error)
GrantTeamAccess(ctx context.Context, team *Team, userId string, role string) error
RevokeTeamAccess(ctx context.Context, team *Team, userId string, role string) error
GrantTeamAccess(ctx context.Context, team *Group, userId string, role string) error
RevokeTeamAccess(ctx context.Context, team *Group, userId string, role string) error
GrantProjectAccess(ctx context.Context, project *Project, userId string, role string) error
RevokeProjectAccess(ctx context.Context, project *Project, userId string, role string) error
GrantOrganizationAccess(ctx context.Context, organization *Organization, userId string, role string) error
Expand Down Expand Up @@ -145,13 +153,86 @@ func (c *client) GetAdminsOfGivenResourceType(ctx context.Context, id string, re
return userEmails, err
}

func (c *client) GetTeams(ctx context.Context) ([]*Team, error) {
func (c *client) GetGroupRelations(ctx context.Context, id string, role string) ([]string, error) {
endPoint := fmt.Sprintf("%s/%s/relations?role=%s", groupsEndpoint, id, role)
req, err := c.newRequest(http.MethodGet, endPoint, nil, "")
if err != nil {
return nil, err
}

var groupRelations []*GroupRelation
var response interface{}
if _, err := c.do(ctx, req, &response); err != nil {
return nil, err
}
if v, ok := response.(map[string]interface{}); ok && v[relationsConst] != nil {
err = mapstructure.Decode(v[relationsConst], &groupRelations)
}

var userEmails []string
for _, relation := range groupRelations {
userEmails = append(userEmails, relation.User.Email)
}

return userEmails, err
}

func (c *client) CreateRelation(ctx context.Context, objectId string, objectNamespace string, subject string, role string) error {
body := Relation{
ObjectId: objectId,
ObjectNamespace: objectNamespace,
Subject: subject,
RoleName: role,
}

req, err := c.newRequest(http.MethodPost, relationsEndpoint, body, "")
if err != nil {
return err
}

var relation *Relation
var response interface{}
if _, err := c.do(ctx, req, &response); err != nil {
return err
}

if v, ok := response.(map[string]interface{}); ok && v[relationConst] != nil {
err = mapstructure.Decode(v[relationConst], &relation)
if err != nil {
return err
}
}

c.logger.Info(ctx, "Relation created for namespace ", objectNamespace, "relation id", relation.Id)
return nil
}

func (c *client) DeleteRelation(ctx context.Context, objectId string, subjectId string, role string) error {
deleteRelationEndpoint := fmt.Sprintf("%s/%s/subject/%s/role/%s", objectEndpoint, objectId, subjectId, role)
req, err := c.newRequest(http.MethodDelete, deleteRelationEndpoint, nil, "")
if err != nil {
return err
}

var response interface{}
if _, err := c.do(ctx, req, &response); err != nil {
return err
}

if v, ok := response.(map[string]interface{}); ok && v["message"] != nil {
c.logger.Info(ctx, "Relation deleted for object", objectId, "subject", subjectId, "role", role)
return nil
}
return nil
}

func (c *client) GetTeams(ctx context.Context) ([]*Group, error) {
req, err := c.newRequest(http.MethodGet, groupsEndpoint, nil, "")
if err != nil {
return nil, err
}

var teams []*Team
var teams []*Group
var response interface{}
if _, err := c.do(ctx, req, &response); err != nil {
return nil, err
Expand All @@ -162,7 +243,7 @@ func (c *client) GetTeams(ctx context.Context) ([]*Team, error) {
}

for _, team := range teams {
admins, err := c.GetAdminsOfGivenResourceType(ctx, team.ID, groupsEndpoint)
admins, err := c.GetGroupRelations(ctx, team.ID, managerRoleConst)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -233,158 +314,57 @@ func (c *client) GetOrganizations(ctx context.Context) ([]*Organization, error)
return organizations, err
}

func (c *client) GrantTeamAccess(ctx context.Context, resource *Team, userId string, role string) error {
body := make(map[string][]string)
body["userIds"] = append(body["userIds"], userId)

endPoint := path.Join(groupsEndpoint, "/", resource.ID, "/", role)
req, err := c.newRequest(http.MethodPost, endPoint, body, "")
func (c *client) GrantTeamAccess(ctx context.Context, resource *Group, userId string, role string) error {
err := c.CreateRelation(ctx, resource.ID, groupNamespaceConst, fmt.Sprintf("%s:%s", userNamespaceConst, userId), role)
if err != nil {
return err
}

var users []*User
var response interface{}
if _, err := c.do(ctx, req, &response); err != nil {
return err
}

if v, ok := response.(map[string]interface{}); ok && v[usersConst] != nil {
err = mapstructure.Decode(v[usersConst], &users)
if err != nil {
return err
}
}

c.logger.Info(ctx, "Team access to the user,", "total users", len(users), req.URL)

c.logger.Info(ctx, "Team access created for user", userId)
return nil
}

func (c *client) GrantProjectAccess(ctx context.Context, resource *Project, userId string, role string) error {
body := make(map[string][]string)
body["userIds"] = append(body["userIds"], userId)

endPoint := path.Join(projectsEndpoint, "/", resource.ID, "/", role)
req, err := c.newRequest(http.MethodPost, endPoint, body, "")
err := c.CreateRelation(ctx, resource.ID, projectNamespaceConst, fmt.Sprintf("%s:%s", userNamespaceConst, userId), role)
if err != nil {
return err
}

var users []*User
var response interface{}
if _, err := c.do(ctx, req, &response); err != nil {
return err
}

if v, ok := response.(map[string]interface{}); ok && v[usersConst] != nil {
err = mapstructure.Decode(v[usersConst], &users)
if err != nil {
return err
}
}

c.logger.Info(ctx, "Project access to the user,", "total users", len(users), req.URL)
c.logger.Info(ctx, "Project access created for user", userId)
return nil
}

func (c *client) GrantOrganizationAccess(ctx context.Context, resource *Organization, userId string, role string) error {
body := make(map[string][]string)
body["userIds"] = append(body["userIds"], userId)

endPoint := path.Join(organizationEndpoint, "/", resource.ID, "/", role)
req, err := c.newRequest(http.MethodPost, endPoint, body, "")

err := c.CreateRelation(ctx, resource.ID, organizationNamespaceConst, fmt.Sprintf("%s:%s", userNamespaceConst, userId), role)
if err != nil {
return err
}

var users []*User
var response interface{}
if _, err := c.do(ctx, req, &response); err != nil {
return err
}

if v, ok := response.(map[string]interface{}); ok && v[usersConst] != nil {
err = mapstructure.Decode(v[usersConst], &users)
if err != nil {
return err
}
}

c.logger.Info(ctx, "Organization access to the user,", "total users", len(users), req.URL)
c.logger.Info(ctx, "Organization access created for user", userId)
return nil
}

func (c *client) RevokeTeamAccess(ctx context.Context, resource *Team, userId string, role string) error {
endPoint := path.Join(groupsEndpoint, "/", resource.ID, "/", role, "/", userId)
req, err := c.newRequest(http.MethodDelete, endPoint, "", "")
func (c *client) RevokeTeamAccess(ctx context.Context, resource *Group, userId string, role string) error {
err := c.DeleteRelation(ctx, resource.ID, userId, role)
if err != nil {
return err
}

var success successAccess
var response interface{}
if _, err := c.do(ctx, req, &response); err != nil {
return err
}

if v, ok := response.(map[string]interface{}); ok && v != nil {
err = mapstructure.Decode(v, &success)
if err != nil {
return err
}
}

c.logger.Info(ctx, "Remove access of the user from team,", "Users", userId, req.URL)
c.logger.Info(ctx, "Remove access of the user from team,", "Users", userId, resource.ID)
return nil
}

func (c *client) RevokeProjectAccess(ctx context.Context, resource *Project, userId string, role string) error {
endPoint := path.Join(projectsEndpoint, "/", resource.ID, "/", role, "/", userId)
req, err := c.newRequest(http.MethodDelete, endPoint, "", "")
err := c.DeleteRelation(ctx, resource.ID, userId, role)
if err != nil {
return err
}

var success successAccess
var response interface{}
if _, err := c.do(ctx, req, &response); err != nil {
return err
}

if v, ok := response.(map[string]interface{}); ok && v != nil {
err = mapstructure.Decode(v, &success)
if err != nil {
return err
}
}

c.logger.Info(ctx, "Remove access of the user from project", "Users", userId, req.URL)
c.logger.Info(ctx, "Remove access of the user from project,", "Users", userId, resource.ID)
return nil
}

func (c *client) RevokeOrganizationAccess(ctx context.Context, resource *Organization, userId string, role string) error {
endPoint := path.Join(organizationEndpoint, "/", resource.ID, "/", role, "/", userId)
req, err := c.newRequest(http.MethodDelete, endPoint, "", "")
err := c.DeleteRelation(ctx, resource.ID, userId, role)
if err != nil {
return err
}

var success successAccess
var response interface{}
if _, err := c.do(ctx, req, &response); err != nil {
return err
}

if v, ok := response.(map[string]interface{}); ok && v != nil {
err = mapstructure.Decode(v, &success)
if err != nil {
return err
}
}

c.logger.Info(ctx, "Remove access of the user from organization", "Users", userId, req.URL)
c.logger.Info(ctx, "Remove access of the user from organization,", "Users", userId, resource.ID)
return nil
}

Expand Down
Loading

0 comments on commit afbdc45

Please sign in to comment.