diff --git a/cmd/resource.go b/cmd/resource.go index e76d00d5c..cfa4b5c09 100644 --- a/cmd/resource.go +++ b/cmd/resource.go @@ -38,7 +38,7 @@ func ResourceCmd(c *app.CLIConfig, adapter handlerv1beta1.ProtoAdapter) *cobra.C } func listResourcesCmd(c *app.CLIConfig, adapter handlerv1beta1.ProtoAdapter) *cobra.Command { - var providerType, providerURN, resourceType, resourceURN, name, format string + var providerType, providerURN, resourceType, resourceURN, name string var isDeleted bool var details []string @@ -78,6 +78,11 @@ func listResourcesCmd(c *app.CLIConfig, adapter handlerv1beta1.ProtoAdapter) *co return err } + format, err := cmd.Flags().GetString("output") + if err != nil { + return err + } + if format != "" { var resources []*domain.Resource for _, r := range res.GetResources() { @@ -121,20 +126,18 @@ func listResourcesCmd(c *app.CLIConfig, adapter handlerv1beta1.ProtoAdapter) *co cmd.Flags().StringVarP(&name, "name", "n", "", "Filter by name") cmd.Flags().StringArrayVarP(&details, "details", "d", nil, "Filter by details object values. Example: --details=key1.key2:value") cmd.Flags().BoolVarP(&isDeleted, "deleted", "D", false, "Show deleted resources") - cmd.Flags().StringVarP(&format, "format", "f", "", "Format of output - json yaml prettyjson etc") return cmd } func viewResourceCmd(c *app.CLIConfig, adapter handlerv1beta1.ProtoAdapter) *cobra.Command { - var format string var metadata bool cmd := &cobra.Command{ Use: "view", Short: "View a resource details", Example: heredoc.Doc(` - $ guardian resource view --format=json --metadata=true + $ guardian resource view --output=json --metadata=true `), Annotations: map[string]string{ "group:core": "true", @@ -159,8 +162,14 @@ func viewResourceCmd(c *app.CLIConfig, adapter handlerv1beta1.ProtoAdapter) *cob return err } + format, err := cmd.Flags().GetString("output") + if err != nil { + return err + } + if format != "" { r := adapter.FromResourceProto(res.GetResource()) + spinner.Stop() if err := printer.Text(r, format); err != nil { return fmt.Errorf("failed to parse resources: %v", err) } @@ -178,6 +187,7 @@ func viewResourceCmd(c *app.CLIConfig, adapter handlerv1beta1.ProtoAdapter) *cob r.GetName(), }) + spinner.Stop() printer.Table(os.Stdout, report) } @@ -196,12 +206,12 @@ func viewResourceCmd(c *app.CLIConfig, adapter handlerv1beta1.ProtoAdapter) *cob } } + spinner.Stop() return nil }, } cmd.Flags().BoolVarP(&metadata, "metadata", "m", false, "Set if you want to see metadata") - cmd.Flags().StringVarP(&format, "format", "f", "", "Format of output - json yaml prettyjson etc") return cmd } @@ -249,7 +259,6 @@ func setResourceCmd(c *app.CLIConfig, adapter handlerv1beta1.ProtoAdapter) *cobr } spinner.Stop() - fmt.Println("Successfully updated metadata") return nil diff --git a/core/policy/service.go b/core/policy/service.go index b2c856802..ca6bb1060 100644 --- a/core/policy/service.go +++ b/core/policy/service.go @@ -221,6 +221,7 @@ func (s *Service) validateRequirements(requirements []*domain.Requirement) error Role: aa.Role, Options: aa.Options, } + appeal.SetDefaults() if err := s.providerService.ValidateAppeal(appeal, provider); err != nil { return fmt.Errorf("requirement[%v].appeals[%v]: %w", i, j, err) } diff --git a/core/policy/service_test.go b/core/policy/service_test.go index 3514b30e7..c23e7cd7f 100644 --- a/core/policy/service_test.go +++ b/core/policy/service_test.go @@ -526,6 +526,7 @@ func (s *ServiceTestSuite) TestPolicyRequirements() { Role: aa.Role, Options: aa.Options, } + expectedAppeal.SetDefaults() s.mockProviderService. On("ValidateAppeal", expectedAppeal, expectedProvider). Return(nil). diff --git a/plugins/providers/bigquery/provider.go b/plugins/providers/bigquery/provider.go index ef3efc92e..8e9815926 100644 --- a/plugins/providers/bigquery/provider.go +++ b/plugins/providers/bigquery/provider.go @@ -2,6 +2,7 @@ package bigquery import ( "context" + "errors" "strings" "github.com/mitchellh/mapstructure" @@ -118,6 +119,9 @@ func (p *Provider) GrantAccess(pc *domain.ProviderConfig, a *domain.Appeal) erro for _, p := range permissions { if err := bqClient.GrantDatasetAccess(ctx, d, a.AccountID, string(p)); err != nil { + if errors.Is(err, ErrPermissionAlreadyExists) { + return nil + } return err } } @@ -131,6 +135,9 @@ func (p *Provider) GrantAccess(pc *domain.ProviderConfig, a *domain.Appeal) erro for _, p := range permissions { if err := bqClient.GrantTableAccess(ctx, t, a.AccountType, a.AccountID, string(p)); err != nil { + if errors.Is(err, ErrPermissionAlreadyExists) { + return nil + } return err } } @@ -169,6 +176,9 @@ func (p *Provider) RevokeAccess(pc *domain.ProviderConfig, a *domain.Appeal) err for _, p := range permissions { if err := bqClient.RevokeDatasetAccess(ctx, d, a.AccountID, string(p)); err != nil { + if errors.Is(err, ErrPermissionNotFound) { + return nil + } return err } } @@ -182,6 +192,9 @@ func (p *Provider) RevokeAccess(pc *domain.ProviderConfig, a *domain.Appeal) err for _, p := range permissions { if err := bqClient.RevokeTableAccess(ctx, t, a.AccountType, a.AccountID, string(p)); err != nil { + if errors.Is(err, ErrPermissionNotFound) { + return nil + } return err } } diff --git a/plugins/providers/gcloudiam/provider.go b/plugins/providers/gcloudiam/provider.go index a8f6f5c5b..ec36de7a7 100644 --- a/plugins/providers/gcloudiam/provider.go +++ b/plugins/providers/gcloudiam/provider.go @@ -1,6 +1,7 @@ package gcloudiam import ( + "errors" "fmt" "strings" @@ -74,7 +75,13 @@ func (p *Provider) GrantAccess(pc *domain.ProviderConfig, a *domain.Appeal) erro } if a.Resource.Type == ResourceTypeProject || a.Resource.Type == ResourceTypeOrganization { - return client.GrantAccess(a.AccountType, a.AccountID, a.Role) + if err := client.GrantAccess(a.AccountType, a.AccountID, a.Role); err != nil { + if errors.Is(err, ErrPermissionAlreadyExists) { + return nil + } + return err + } + return nil } return ErrInvalidResourceType @@ -92,7 +99,13 @@ func (p *Provider) RevokeAccess(pc *domain.ProviderConfig, a *domain.Appeal) err } if a.Resource.Type == ResourceTypeProject || a.Resource.Type == ResourceTypeOrganization { - return client.RevokeAccess(a.AccountType, a.AccountID, a.Role) + if err := client.RevokeAccess(a.AccountType, a.AccountID, a.Role); err != nil { + if errors.Is(err, ErrPermissionNotFound) { + return nil + } + return err + } + return nil } return ErrInvalidResourceType diff --git a/store/model/appeal.go b/store/model/appeal.go index f795062fd..e89d1351a 100644 --- a/store/model/appeal.go +++ b/store/model/appeal.go @@ -102,6 +102,9 @@ func (m *Appeal) FromDomain(a *domain.Appeal) error { m.Options = datatypes.JSON(options) m.Labels = datatypes.JSON(labels) m.Details = datatypes.JSON(details) + m.RevokedBy = a.RevokedBy + m.RevokedAt = a.RevokedAt + m.RevokeReason = a.RevokeReason m.Approvals = approvals m.CreatedAt = a.CreatedAt m.UpdatedAt = a.UpdatedAt @@ -172,6 +175,9 @@ func (m *Appeal) ToDomain() (*domain.Appeal, error) { Role: m.Role, Options: options, Details: details, + RevokedBy: m.RevokedBy, + RevokedAt: m.RevokedAt, + RevokeReason: m.RevokeReason, Labels: labels, Approvals: approvals, Resource: resource, diff --git a/store/model/policy.go b/store/model/policy.go index 7c73cdb95..03703a897 100644 --- a/store/model/policy.go +++ b/store/model/policy.go @@ -11,15 +11,16 @@ import ( // Policy is the database model for policy type Policy struct { - ID string `gorm:"primaryKey"` - Version uint `gorm:"primaryKey"` - Description string - Steps datatypes.JSON - Labels datatypes.JSON - IAM datatypes.JSON - CreatedAt time.Time `gorm:"autoCreateTime"` - UpdatedAt time.Time `gorm:"autoUpdateTime"` - DeletedAt gorm.DeletedAt `gorm:"index"` + ID string `gorm:"primaryKey"` + Version uint `gorm:"primaryKey"` + Description string + Steps datatypes.JSON + Labels datatypes.JSON + Requirements datatypes.JSON + IAM datatypes.JSON + CreatedAt time.Time `gorm:"autoCreateTime"` + UpdatedAt time.Time `gorm:"autoUpdateTime"` + DeletedAt gorm.DeletedAt `gorm:"index"` } // TableName overrides the table name @@ -39,6 +40,11 @@ func (m *Policy) FromDomain(p *domain.Policy) error { return err } + requirements, err := json.Marshal(p.Requirements) + if err != nil { + return err + } + iam, err := json.Marshal(p.IAM) if err != nil { return err @@ -49,6 +55,7 @@ func (m *Policy) FromDomain(p *domain.Policy) error { m.Description = p.Description m.Steps = datatypes.JSON(steps) m.Labels = datatypes.JSON(labels) + m.Requirements = datatypes.JSON(requirements) m.IAM = datatypes.JSON(iam) m.CreatedAt = p.CreatedAt m.UpdatedAt = p.UpdatedAt @@ -68,6 +75,13 @@ func (m *Policy) ToDomain() (*domain.Policy, error) { return nil, err } + var requirements []*domain.Requirement + if m.Requirements != nil { + if err := json.Unmarshal(m.Requirements, &requirements); err != nil { + return nil, err + } + } + var iam *domain.IAMConfig if m.IAM != nil { if err := json.Unmarshal(m.IAM, &iam); err != nil { @@ -76,13 +90,14 @@ func (m *Policy) ToDomain() (*domain.Policy, error) { } return &domain.Policy{ - ID: m.ID, - Version: m.Version, - Description: m.Description, - Steps: steps, - Labels: labels, - IAM: iam, - CreatedAt: m.CreatedAt, - UpdatedAt: m.UpdatedAt, + ID: m.ID, + Version: m.Version, + Description: m.Description, + Steps: steps, + Labels: labels, + Requirements: requirements, + IAM: iam, + CreatedAt: m.CreatedAt, + UpdatedAt: m.UpdatedAt, }, nil } diff --git a/store/postgres/policy_repository_test.go b/store/postgres/policy_repository_test.go index ebd1dd84a..4dbd2f8c4 100644 --- a/store/postgres/policy_repository_test.go +++ b/store/postgres/policy_repository_test.go @@ -39,6 +39,7 @@ func (s *PolicyRepositoryTestSuite) SetupTest() { "description", "steps", "labels", + "requirements", "iam", "created_at", "updated_at", @@ -50,7 +51,7 @@ func (s *PolicyRepositoryTestSuite) TearDownTest() { } func (s *PolicyRepositoryTestSuite) TestCreate() { - expectedQuery := regexp.QuoteMeta(`INSERT INTO "policies" ("id","version","description","steps","labels","iam","created_at","updated_at","deleted_at") VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9)`) + expectedQuery := regexp.QuoteMeta(`INSERT INTO "policies" ("id","version","description","steps","labels","requirements","iam","created_at","updated_at","deleted_at") VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10)`) s.Run("should return error if got error from db transaction", func() { p := &domain.Policy{} @@ -62,6 +63,7 @@ func (s *PolicyRepositoryTestSuite) TestCreate() { "null", "null", "null", + "null", utils.AnyTime{}, utils.AnyTime{}, gorm.DeletedAt{}, @@ -89,6 +91,7 @@ func (s *PolicyRepositoryTestSuite) TestCreate() { "null", "null", "null", + "null", utils.AnyTime{}, utils.AnyTime{}, gorm.DeletedAt{}, @@ -141,6 +144,7 @@ func (s *PolicyRepositoryTestSuite) TestFind() { "null", "null", "null", + "null", now, now, ) @@ -212,6 +216,7 @@ func (s *PolicyRepositoryTestSuite) TestGetOne() { "null", "null", "null", + "null", now, now, }