Skip to content

Commit

Permalink
SCALRCORE-28980 API > Policy Engine > Enforce policy group for all cu…
Browse files Browse the repository at this point in the history
…rrent and future environments
  • Loading branch information
denkl committed Nov 17, 2023
1 parent c357edb commit ad96a52
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 18 deletions.
2 changes: 1 addition & 1 deletion docs/data-sources/policy_group.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ data "scalr_policy_group" "example2" {

### Read-Only

- `environments` (List of String) A list of the environments the policy group is linked to.
- `environments` (List of String) A list of the environments the policy group is linked to, or ["*"] if enforced in all environments.
- `error_message` (String) An error details if Scalr failed to process the policy group.
- `opa_version` (String) The version of the Open Policy Agent that the policy group is using.
- `policies` (List of Object) A list of the OPA policies the policy group verifies each run. (see [below for nested schema](#nestedatt--policies))
Expand Down
2 changes: 1 addition & 1 deletion docs/resources/policy_group.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ resource "scalr_policy_group" "example" {

- `account_id` (String) The identifier of the Scalr account, in the format `acc-<RANDOM STRING>`.
- `opa_version` (String) The version of Open Policy Agent to run policies against. If omitted, the system default version is assigned.
- `environments` (List of String) A list of the environments the policy group is linked to. Use ["*"] to enforce in all environments.

### Read-Only

- `environments` (List of String) A list of the environments the policy group is linked to.
- `error_message` (String) A detailed error if Scalr failed to process the policy group.
- `id` (String) The ID of this resource.
- `policies` (List of Object) A list of the OPA policies the group verifies each run. (see [below for nested schema](#nestedatt--policies))
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ require (
github.com/hashicorp/terraform-plugin-docs v0.16.0
github.com/hashicorp/terraform-plugin-sdk/v2 v2.24.1
github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734
github.com/scalr/go-scalr v0.0.0-20231004160327-c0bbb43d3b4f
github.com/scalr/go-scalr v0.0.0-20231117090940-913594e4e135
)

require (
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -260,8 +260,8 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww=
github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY=
github.com/scalr/go-scalr v0.0.0-20231004160327-c0bbb43d3b4f h1:2acK1M8YNfTe1rpn9UUhR0UIGMWCmHw4BMxQCCM7lPo=
github.com/scalr/go-scalr v0.0.0-20231004160327-c0bbb43d3b4f/go.mod h1:p34SHb25YRvbgft7SUjSDYESeoQhWzAlxGXId/BbaSE=
github.com/scalr/go-scalr v0.0.0-20231117090940-913594e4e135 h1:EAfMV+rwOLld3pJPwUnrFRyt3jxYx/N0q+fjextco0s=
github.com/scalr/go-scalr v0.0.0-20231117090940-913594e4e135/go.mod h1:p34SHb25YRvbgft7SUjSDYESeoQhWzAlxGXId/BbaSE=
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
Expand Down
8 changes: 5 additions & 3 deletions scalr/data_source_scalr_policy_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,13 +183,15 @@ func dataSourceScalrPolicyGroupRead(ctx context.Context, d *schema.ResourceData,
}
_ = d.Set("policies", policies)

var envs []string
if len(pg.Environments) != 0 {
if pg.IsEnforced {
_ = d.Set("environments", []string{"*"})
} else {
envs := make([]string, 0)
for _, env := range pg.Environments {
envs = append(envs, env.ID)
}
_ = d.Set("environments", envs)
}
_ = d.Set("environments", envs)

d.SetId(pg.ID)

Expand Down
102 changes: 92 additions & 10 deletions scalr/resource_scalr_policy_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ package scalr
import (
"context"
"errors"
"fmt"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"log"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/scalr/go-scalr"
"log"
)

func resourceScalrPolicyGroup() *schema.Resource {
Expand Down Expand Up @@ -110,13 +110,36 @@ func resourceScalrPolicyGroup() *schema.Resource {
"environments": {
Description: "A list of the environments the policy group is linked to.",
Type: schema.TypeList,
Computed: true,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
},
}
}

func parseEnvironmentDefinitions(d *schema.ResourceData) ([]*scalr.Environment, error) {
environmentIDs := d.Get("environments").([]interface{})
err := ValidateIDsDefinitions(environmentIDs)
if err != nil {
return nil, fmt.Errorf("got error during parsing environments: %s", err.Error())
}

environments := make([]*scalr.Environment, 0)
var hasWildcard bool
for i, environmentID := range environmentIDs {
environments = append(environments, &scalr.Environment{ID: environmentID.(string)})

if environmentID.(string) == "*" {
hasWildcard = true
}
if i != 0 && hasWildcard {
return nil, fmt.Errorf("impossible to enforce the policy group in all and on a limited list of environments. Please remove either wildcard or environment identifiers")
}
}

return environments, nil
}

func resourceScalrPolicyGroupCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
scalrClient := meta.(*scalr.Client)

Expand All @@ -143,6 +166,16 @@ func resourceScalrPolicyGroupCreate(ctx context.Context, d *schema.ResourceData,
VcsProvider: &scalr.VcsProvider{ID: vcsProviderID},
}

environments, err := parseEnvironmentDefinitions(d)
if err != nil {
return diag.FromErr(err)
}
if (len(environments) == 1) && (environments[0].ID == "*") {
opts.IsEnforced = scalr.Bool(true)
} else {
opts.IsEnforced = scalr.Bool(false)
}

// Optional attributes
if opaVersion, ok := d.GetOk("opa_version"); ok {
opts.OpaVersion = scalr.String(opaVersion.(string))
Expand All @@ -154,6 +187,25 @@ func resourceScalrPolicyGroupCreate(ctx context.Context, d *schema.ResourceData,
}

d.SetId(pg.ID)

if len(environments) > 0 && !*opts.IsEnforced {
pgEnvs := make([]*scalr.PolicyGroupEnvironment, 0)
for _, env := range environments {
pgEnvs = append(pgEnvs, &scalr.PolicyGroupEnvironment{ID: env.ID})
}
pgEnvsOpts := scalr.PolicyGroupEnvironmentsCreateOptions{
PolicyGroupID: pg.ID,
PolicyGroupEnvironments: pgEnvs,
}
err = scalrClient.PolicyGroupEnvironments.Create(ctx, pgEnvsOpts)
if err != nil {
defer func(ctx context.Context, pgID string) {
_ = scalrClient.PolicyGroups.Delete(ctx, pgID)
}(ctx, pg.ID)
return diag.Errorf("error linking environments to policy group '%s': %v", name, err)
}
}

return resourceScalrPolicyGroupRead(ctx, d, meta)
}

Expand Down Expand Up @@ -197,13 +249,16 @@ func resourceScalrPolicyGroupRead(ctx context.Context, d *schema.ResourceData, m
}
_ = d.Set("policies", policies)

var envs []string
if len(pg.Environments) != 0 {
for _, env := range pg.Environments {
envs = append(envs, env.ID)
if pg.IsEnforced {
allEnvironments := []string{"*"}
_ = d.Set("environments", allEnvironments)
} else {
environmentIDs := make([]string, 0)
for _, environment := range pg.Environments {
environmentIDs = append(environmentIDs, environment.ID)
}
_ = d.Set("environments", environmentIDs)
}
_ = d.Set("environments", envs)

return nil
}
Expand All @@ -214,7 +269,8 @@ func resourceScalrPolicyGroupUpdate(ctx context.Context, d *schema.ResourceData,
id := d.Id()

if d.HasChange("name") || d.HasChange("opa_version") ||
d.HasChange("vcs_provider_id") || d.HasChange("vcs_repo") {
d.HasChange("vcs_provider_id") || d.HasChange("vcs_repo") ||
d.HasChange("environments") {

name := d.Get("name").(string)
vcsProviderID := d.Get("vcs_provider_id").(string)
Expand All @@ -239,11 +295,37 @@ func resourceScalrPolicyGroupUpdate(ctx context.Context, d *schema.ResourceData,
opts.OpaVersion = scalr.String(opaVersion.(string))
}

environments, err := parseEnvironmentDefinitions(d)
if err != nil {
return diag.FromErr(err)
}
if (len(environments) == 1) && (environments[0].ID == "*") {
opts.IsEnforced = scalr.Bool(true)
} else {
opts.IsEnforced = scalr.Bool(false)
}

log.Printf("[DEBUG] Update policy group %s", id)
_, err := scalrClient.PolicyGroups.Update(ctx, id, opts)
_, err = scalrClient.PolicyGroups.Update(ctx, id, opts)
if err != nil {
return diag.Errorf("error updating policy group %s: %v", id, err)
}

if !*opts.IsEnforced {
pgEnvs := make([]*scalr.PolicyGroupEnvironment, 0)
for _, env := range environments {
pgEnvs = append(pgEnvs, &scalr.PolicyGroupEnvironment{ID: env.ID})
}
pgEnvsOpts := scalr.PolicyGroupEnvironmentsUpdateOptions{
PolicyGroupID: id,
PolicyGroupEnvironments: pgEnvs,
}

err = scalrClient.PolicyGroupEnvironments.Update(ctx, pgEnvsOpts)
if err != nil {
return diag.Errorf("error updating environments for policy group %s: %v", id, err)
}
}
}

return resourceScalrPolicyGroupRead(ctx, d, meta)
Expand Down

0 comments on commit ad96a52

Please sign in to comment.