Skip to content

Commit

Permalink
Merge pull request #6 from permitio/ori/per-7928-add-resource-sets-to…
Browse files Browse the repository at this point in the history
…-tf-provider

Begin condition set implementation
  • Loading branch information
omer9564 committed Sep 19, 2023
2 parents ea8db99 + 06f0485 commit 5ea8f05
Show file tree
Hide file tree
Showing 10 changed files with 822 additions and 5 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,4 @@ website/vendor

# Keep windows files with windows line endings
*.winfile eol=crlf
examples/.terraform.lock.hcl
61 changes: 61 additions & 0 deletions examples/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,67 @@ resource "permitio_role" "admin" {
]
}

resource "permitio_user_set" "privileged_users" {
key = "privileged_users"
name = "Privileged Users"
conditions = jsonencode({
"allOf" : [
{
"allOf" : [
{
"subject.email" = {
contains = "@admin.com"
},
}
]
}
]
})
}

resource "permitio_user_set" "unprivileged_users" {
key = "unprivileged_users"
name = "Unprivileged Users"
conditions = jsonencode({
"allOf" : [
{
"allOf" : [
{
"subject.email" = {
contains = "@user.com"
},
}
]
}
]
})
}

resource "permitio_resource_set" "secret_docs" {
key = "secret_docs"
name = "Secret Docs"
resource = permitio_resource.document.key
conditions = jsonencode({
"allOf" : [
{
"allOf" : [
{
"resource.title" = {
contains = "Rye"
},
}
]
}
]
})
}

resource "permitio_condition_set_rule" "allow_privileged_users_to_read_secret_docs" {
user_set = permitio_user_set.privileged_users.key
resource_set = permitio_resource_set.secret_docs.key
permission = "document:read"
}

output "my_resource" {
value = permitio_role.admin
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ require (
github.com/hashicorp/terraform-plugin-go v0.18.0
github.com/hashicorp/terraform-plugin-log v0.9.0
github.com/hashicorp/terraform-plugin-testing v1.4.0
github.com/permitio/permit-golang v0.0.13
github.com/permitio/permit-golang v0.0.18
)

require (
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -240,8 +240,8 @@ github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zx
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/permitio/permit-golang v0.0.13 h1:fQWKLw9YQgu9MClsRi/6jA0wXbXZxT2o+w2hRF8VTcI=
github.com/permitio/permit-golang v0.0.13/go.mod h1:phP2AVSL3bgDKfhhmhPt/VJAN8UUDJoQtVjUKRfY5Ck=
github.com/permitio/permit-golang v0.0.18 h1:94OQF7yTD6CCf72ARkVkXRGjZR7ToFYIkYvACf5nnU0=
github.com/permitio/permit-golang v0.0.18/go.mod h1:phP2AVSL3bgDKfhhmhPt/VJAN8UUDJoQtVjUKRfY5Ck=
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
Expand Down
64 changes: 64 additions & 0 deletions internal/provider/conditionset_rules/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package conditionsetrules

import (
"context"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/permitio/permit-golang/pkg/permit"
)

type ConditionSetRuleModel struct {
Id types.String `tfsdk:"id"`
OrganizationId types.String `tfsdk:"organization_id"`
ProjectId types.String `tfsdk:"project_id"`
EnvironmentId types.String `tfsdk:"environment_id"`
UserSet types.String `tfsdk:"user_set"`
Permission types.String `tfsdk:"permission"`
ResourceSet types.String `tfsdk:"resource_set"`
}

type ConditionSetRuleClient struct {
client *permit.Client
}

func (c *ConditionSetRuleClient) Read(ctx context.Context, data ConditionSetRuleModel) (ConditionSetRuleModel, error) {
_, err := c.client.Api.ConditionSets.ListSetPermissions(
ctx,
data.UserSet.ValueString(),
data.Permission.ValueString(),
data.ResourceSet.ValueString(),
)

if err != nil {
return ConditionSetRuleModel{}, err
}

return data, nil
}

func (c *ConditionSetRuleClient) Create(ctx context.Context, rulePlan *ConditionSetRuleModel) error {
ruleRead, err := c.client.Api.ConditionSets.AssignSetPermissions(
ctx,
rulePlan.UserSet.ValueString(),
rulePlan.Permission.ValueString(),
rulePlan.ResourceSet.ValueString())

if err != nil {
return err
}

rulePlan.Id = types.StringValue(ruleRead[0].Id)
rulePlan.OrganizationId = types.StringValue(ruleRead[0].OrganizationId)
rulePlan.ProjectId = types.StringValue(ruleRead[0].ProjectId)
rulePlan.EnvironmentId = types.StringValue(ruleRead[0].EnvironmentId)

return nil
}

func (c *ConditionSetRuleClient) Delete(ctx context.Context, rulePlan *ConditionSetRuleModel) error {
return c.client.Api.ConditionSets.UnassignSetPermissions(
ctx,
rulePlan.UserSet.ValueString(),
rulePlan.Permission.ValueString(),
rulePlan.ResourceSet.ValueString(),
)
}
180 changes: 180 additions & 0 deletions internal/provider/conditionset_rules/resource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
package conditionsetrules

import (
"context"
"fmt"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
"github.com/permitio/permit-golang/pkg/permit"
)

// Ensure the implementation satisfies the expected interfaces.
var (
_ resource.Resource = &ConditionSetRuleResource{}
_ resource.ResourceWithConfigure = &ConditionSetRuleResource{}
)

func NewConditionSetRuleResource() resource.Resource {
return &ConditionSetRuleResource{}
}

type ConditionSetRuleResource struct {
client ConditionSetRuleClient
}

func (c *ConditionSetRuleResource) Configure(_ context.Context, request resource.ConfigureRequest, response *resource.ConfigureResponse) {
if request.ProviderData == nil {
return
}

permitClient, ok := request.ProviderData.(*permit.Client)

if !ok {
response.Diagnostics.AddError(
"Unexpected Resource Configure Type",
fmt.Sprintf("Expected *permit.Client, got: %T. Please report this issue to the provider developers.", request.ProviderData),
)
return
}

c.client = ConditionSetRuleClient{client: permitClient}
}

func (c *ConditionSetRuleResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
// should be completely implemented in ResourceSet/UserSet
resp.TypeName = req.ProviderTypeName + "_condition_set_rule"
}

func (c *ConditionSetRuleResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: map[string]schema.Attribute{
"id": schema.StringAttribute{
Computed: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.UseStateForUnknown(),
},
},
"organization_id": schema.StringAttribute{
Computed: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.UseStateForUnknown(),
},
},
"project_id": schema.StringAttribute{
Computed: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.UseStateForUnknown(),
},
},
"environment_id": schema.StringAttribute{
Computed: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.UseStateForUnknown(),
},
},
"user_set": schema.StringAttribute{
Required: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.RequiresReplace(),
},
},
"permission": schema.StringAttribute{
Required: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.RequiresReplace(),
},
},
"resource_set": schema.StringAttribute{
Required: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.RequiresReplace(),
},
},
},
}
}

func (c *ConditionSetRuleResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
var (
plan ConditionSetRuleModel
)

diags := req.Plan.Get(ctx, &plan)
resp.Diagnostics.Append(diags...)

if resp.Diagnostics.HasError() {
return
}

if err := c.client.Create(ctx, &plan); err != nil {
resp.Diagnostics.AddError(
"Unable to create condition set rule",
fmt.Sprintf("Unable to create condition set rule: %s", err),
)
return
}

// Set state to fully populated data
diags = resp.State.Set(ctx, plan)
resp.Diagnostics.Append(diags...)

if resp.Diagnostics.HasError() {
return
}
}

func (c *ConditionSetRuleResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
var data ConditionSetRuleModel

resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}

state, err := c.client.Read(ctx, data)

if err != nil {
resp.Diagnostics.AddError(
"Unable to Read Condition Set Rule",
fmt.Sprintf("Unable to read condition set rule: %s, Error: %s", data.Id.String(), err.Error()),
)
return
}

// Set state
diags := resp.State.Set(ctx, &state)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
}

// Update updates the resource and sets the updated Terraform state on success.
func (c *ConditionSetRuleResource) Update(_ context.Context, _ resource.UpdateRequest, _ *resource.UpdateResponse) {
// rules cannot be updated, only replaced - this should never be called
panic("updating ConditionSetRules is not implemented")
}

// Delete deletes the resource and removes the Terraform state on success.
func (c *ConditionSetRuleResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
// Retrieve values from state
var state ConditionSetRuleModel
diags := req.State.Get(ctx, &state)
resp.Diagnostics.Append(diags...)

if resp.Diagnostics.HasError() {
return
}

err := c.client.Delete(ctx, &state)

if err != nil {
resp.Diagnostics.AddError(
"Error Deleting Condition Set Rule",
"Could not delete condition set rule, unexpected error: "+err.Error(),
)
return
}
}
Loading

0 comments on commit 5ea8f05

Please sign in to comment.