Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add OPA support to the policy API's: #579

Merged
merged 3 commits into from Nov 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Expand Up @@ -2,7 +2,8 @@

## Enhancements

* Add OPA support to the Policy Set API's by @mrinalirao [#575](https://github.com/hashicorp/go-tfe/pull/575)
* Add OPA support to the Policy Set APIs by @mrinalirao [#575](https://github.com/hashicorp/go-tfe/pull/575)
* Add OPA support to the Policy APIs by @mrinalirao [#579](https://github.com/hashicorp/go-tfe/pull/579)

# v1.12.0

Expand Down
2 changes: 2 additions & 0 deletions errors.go
Expand Up @@ -199,6 +199,8 @@ var (

ErrRequiredName = errors.New("name is required")

ErrRequiredQuery = errors.New("query cannot be empty")

ErrRequiredEnabled = errors.New("enabled is required")

ErrRequiredEnforce = errors.New("enforce is required")
Expand Down
63 changes: 63 additions & 0 deletions helper_test.go
Expand Up @@ -614,6 +614,40 @@ func createPolicy(t *testing.T, client *Client, org *Organization) (*Policy, fun
}
}

func createPolicyWithOptions(t *testing.T, client *Client, org *Organization, opts PolicyCreateOptions) (*Policy, func()) {
var orgCleanup func()

if org == nil {
org, orgCleanup = createOrganization(t, client)
}

name := randomString(t)
options := PolicyCreateOptions{
mrinalirao marked this conversation as resolved.
Show resolved Hide resolved
Name: String(name),
Kind: opts.Kind,
Query: opts.Query,
Enforce: opts.Enforce,
}

ctx := context.Background()
p, err := client.Policies.Create(ctx, org.Name, options)
if err != nil {
t.Fatal(err)
}

return p, func() {
if err := client.Policies.Delete(ctx, p.ID); err != nil {
t.Errorf("Error destroying policy! WARNING: Dangling resources\n"+
"may exist! The full error is shown below.\n\n"+
"Policy: %s\nError: %s", p.ID, err)
}

if orgCleanup != nil {
orgCleanup()
}
}
}

func createUploadedPolicy(t *testing.T, client *Client, pass bool, org *Organization) (*Policy, func()) {
var orgCleanup func()

Expand Down Expand Up @@ -643,6 +677,35 @@ func createUploadedPolicy(t *testing.T, client *Client, pass bool, org *Organiza
}
}

func createUploadedPolicyWithOptions(t *testing.T, client *Client, pass bool, org *Organization, opts PolicyCreateOptions) (*Policy, func()) {
var orgCleanup func()

if org == nil {
org, orgCleanup = createOrganization(t, client)
}

p, pCleanup := createPolicyWithOptions(t, client, org, opts)

ctx := context.Background()
err := client.Policies.Upload(ctx, p.ID, []byte(fmt.Sprintf("main = rule { %t }", pass)))
if err != nil {
t.Fatal(err)
}

p, err = client.Policies.Read(ctx, p.ID)
if err != nil {
t.Fatal(err)
}

return p, func() {
pCleanup()

if orgCleanup != nil {
orgCleanup()
}
}
}

func createOAuthClient(t *testing.T, client *Client, org *Organization) (*OAuthClient, func()) {
var orgCleanup func()

Expand Down
28 changes: 25 additions & 3 deletions policy.go
Expand Up @@ -48,9 +48,10 @@ type EnforcementLevel string

// List the available enforcement types.
const (
EnforcementAdvisory EnforcementLevel = "advisory"
EnforcementHard EnforcementLevel = "hard-mandatory"
EnforcementSoft EnforcementLevel = "soft-mandatory"
EnforcementAdvisory EnforcementLevel = "advisory"
EnforcementHard EnforcementLevel = "hard-mandatory"
EnforcementSoft EnforcementLevel = "soft-mandatory"
EnforcementMandatory EnforcementLevel = "mandatory"
)

// PolicyList represents a list of policies..
Expand All @@ -63,6 +64,8 @@ type PolicyList struct {
type Policy struct {
ID string `jsonapi:"primary,policies"`
Name string `jsonapi:"attr,name"`
Kind PolicyKind `jsonapi:"attr,kind"`
Query *string `jsonapi:"attr,query"`
Description string `jsonapi:"attr,description"`
Enforce []*Enforcement `jsonapi:"attr,enforce"`
PolicySetCount int `jsonapi:"attr,policy-set-count"`
Expand Down Expand Up @@ -90,6 +93,10 @@ type PolicyListOptions struct {

// Optional: A search string (partial policy name) used to filter the results.
Search string `url:"search[name],omitempty"`

// **Note: This field is still in BETA and subject to change.**
// Optional: A kind string used to filter the results by the policy kind.
Kind PolicyKind `url:"filter[kind],omitempty"`
}

// PolicyCreateOptions represents the options for creating a new policy.
Expand All @@ -103,6 +110,14 @@ type PolicyCreateOptions struct {
// Required: The name of the policy.
Name *string `jsonapi:"attr,name"`

// **Note: This field is still in BETA and subject to change.**
// Optional: The underlying technology that the policy supports. Defaults to Sentinel if not specified for PolicyCreate.
Kind PolicyKind `jsonapi:"attr,kind,omitempty"`

// **Note: This field is still in BETA and subject to change.**
// Optional: The query passed to policy evaluation to determine the result of the policy. Only valid for OPA.
Query *string `jsonapi:"attr,query,omitempty"`

// Optional: A description of the policy's purpose.
Description *string `jsonapi:"attr,description,omitempty"`

Expand All @@ -121,6 +136,10 @@ type PolicyUpdateOptions struct {
// Optional: A description of the policy's purpose.
Description *string `jsonapi:"attr,description,omitempty"`

// **Note: This field is still in BETA and subject to change.**
// Optional: The query passed to policy evaluation to determine the result of the policy. Only valid for OPA.
Query *string `jsonapi:"attr,query,omitempty"`

// Optional: The enforcements of the policy.
Enforce []*EnforcementOptions `jsonapi:"attr,enforce,omitempty"`
}
Expand Down Expand Up @@ -270,6 +289,9 @@ func (o PolicyCreateOptions) valid() error {
if !validStringID(o.Name) {
return ErrInvalidName
}
if o.Kind == OPA && !validString(o.Query) {
return ErrRequiredQuery
}
if o.Enforce == nil {
return ErrRequiredEnforce
}
Expand Down