-
Notifications
You must be signed in to change notification settings - Fork 3
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
ENG-12949: Policy engine providers #547
Conversation
"last_updated": { | ||
Description: "Information about when and by whom the policy was last updated.", | ||
Type: schema.TypeMap, | ||
Optional: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be:
Optional: true, | |
Computed: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks; 4526ad6
"created": { | ||
Description: "Information about when and by whom the policy was created.", | ||
Type: schema.TypeMap, | ||
Optional: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optional: true, | |
Computed: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks 4526ad6
"document": { | ||
Description: "The actual policy document in JSON format.", | ||
Type: schema.TypeString, | ||
Optional: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
document is not optional, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
"enforced": { | ||
Description: "Indicates if the policy is enforced.", | ||
Type: schema.TypeBool, | ||
Optional: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a way to specify what the default is? Not needed if tf assumes the default is the go default for the type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can specify, but looks right to me.
TF:
resource "cyral_policy_v2" "local_policy_example" {
name = "minimal_local_policy"
document = jsonencode({
governedData = {
locations = ["gym_db.users"]
}
readRules = [
{
conditions = [
{
attribute = "identity.userGroups"
operator = "contains"
value = "users"
}
]
constraints = {
datasetRewrite = "SELECT * FROM $${dataset} WHERE email = '$${identity.endUserEmail}'"
}
}
]
})
type = "local"
}
Created policy (GET from API):
{
"policy": {
"id": "5250617c-c5de-43cc-954a-15b6682e97f6",
"name": "minimal_local_policy",
"description": "",
"enabled": false,
"scope": null,
"tags": [],
"validFrom": null,
"validUntil": null,
"document": "{\"governedData\":{\"locations\":[\"gym_db.users\"]},\"readRules\":[{\"conditions\":[{\"attribute\":\"identity.userGroups\",\"operator\":\"contains\",\"value\":\"users\"}],\"constraints\":{\"datasetRewrite\":\"SELECT * FROM ${dataset} WHERE email = '${identity.endUserEmail}'\"}}]}",
"lastUpdated": null,
"created": {
"actor": "sa/default/de84bc5b-8204-43cf-a6ab-e101db2c67f4",
"actorType": "ACTOR_TYPE_API_CLIENT",
"timestamp": "2024-06-12T12:53:44.310243758Z"
},
"enforced": false
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a Default
attribute in the Schema
that can be used for that.
cyral/internal/policyv2/model.go
Outdated
} | ||
|
||
// Normalize the document field before setting it | ||
normalizedDocument, err := normalizeJSON(r.Policy.Document) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need to normalize the JSON?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
code was refactored
cyral/internal/policyv2/model.go
Outdated
|
||
// Normalize the document field before storing it | ||
document := d.Get("document").(string) | ||
normalizedDocument, err := normalizeJSON(document) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As soon as we do this, we lose the original value of document provided by the resource definition (whitespace changes) - this may be the cause of the state mismatch that you're seeing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
code was refactored
cyral/internal/policyv2/model.go
Outdated
r.Policy.LastUpdated = expandChangeInfo(d.Get("last_updated").(map[string]interface{})) | ||
r.Policy.Created = expandChangeInfo(d.Get("created").(map[string]interface{})) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These should probably not be set here since these are computed fields.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
cyral/internal/policyv2/model.go
Outdated
if v == nil { | ||
return "" | ||
} | ||
return v.(string) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could panic if the actual value is not a string. Maybe you should return "" in the (unlikely) case that v is not a string?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
cyral/internal/policyv2/resource.go
Outdated
Computed: true, | ||
}, | ||
"name": { | ||
Description: "...", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
needs to be fixed. Same for description below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
cyral/internal/policyv2/resource.go
Outdated
|
||
func resourceSchema() *schema.Resource { | ||
return &schema.Resource{ | ||
Description: "Some description.", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TBD
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
c8f08ec
to
b2ad3ba
Compare
…eing transferred from the schema to the API."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks OK to me at a high level - will lean on @wcmjunior for more detailed review.
I have some small suggestions that we might want to discuss.
cyral/internal/policyv2/constants.go
Outdated
package policyv2 | ||
|
||
const ( | ||
resourceName = "cyral_policy_v2" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe something like cyral_custom_policy
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's keep as cyral_policy_v2
we will replace cyral_policy
by this new resource in the next major version of the provider. Please also mark the cyral_policy
as deprecated as we should encourage the move.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just rename the policy package with deprecated? Looks like that is what we've done before? Moving the files to deprecated folder won't work with this new model (as it will eventually lead to filename collisions)?
docs/resources/policy_v2.md
Outdated
} | ||
|
||
|
||
resource "cyral_policy_v2" "approval_policy_example" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approval policies are currently "invisible" - also proposed to be not documented to begin with.
Let's have a brief discussion in the next meeting on whether it's desirable to expose this construct in the docs (I don't have any mortal objection against this but we just need to be consistent - if we have them here, the documentation should also cover it).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed in 7833171
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your PR @gengdahlCyral! Hopefully it was easier to create a new resource with the new abstractions. I added a few comments that may help shrink the code as you will reuse some existing functions and some other minor improvements. I will work on a more comprehensive review of the tests and examples in my next review.
cyral/internal/policyv2/constants.go
Outdated
package policyv2 | ||
|
||
const ( | ||
resourceName = "cyral_policy_v2" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's keep as cyral_policy_v2
we will replace cyral_policy
by this new resource in the next major version of the provider. Please also mark the cyral_policy
as deprecated as we should encourage the move.
@@ -0,0 +1,111 @@ | |||
package policyv2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of creating a package policyv2
, it seems to me that creating a v2
package inside policy
is better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
cyral/internal/policyv2/model.go
Outdated
r.Policy.Name = d.Get("name").(string) | ||
r.Policy.Description = d.Get("description").(string) | ||
r.Policy.Enabled = d.Get("enabled").(bool) | ||
r.Policy.Tags = expandStringList(d.Get("tags").([]interface{})) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
r.Policy.Tags = expandStringList(d.Get("tags").([]interface{})) | |
r.Policy.Tags = utils.ConvertFromInterfaceList(d.Get("tags").([]interface{})) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
cyral/internal/policyv2/model.go
Outdated
} | ||
m := s[0].(map[string]interface{}) | ||
scope := Scope{ | ||
RepoIds: expandStringList(m["repo_ids"].([]interface{})), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RepoIds: expandStringList(m["repo_ids"].([]interface{})), | |
RepoIds: utils.ConvertFromInterfaceList(m["repo_ids"].([]interface{})), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
cyral/internal/policyv2/model.go
Outdated
} | ||
|
||
// flattenScope converts the Scope struct to a list of maps | ||
func flattenScope(scope *Scope) []map[string]interface{} { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Scope
should be taught how to perform this operation itself so you would call it like scope.ToMap()
or some other more go-lang appropriate name. :-)
func flattenScope(scope *Scope) []map[string]interface{} { | |
func (s *Scope) ToMap() []map[string]interface{} { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
return &schema.Resource{ | ||
Description: "This data source provides information about a policy.", | ||
ReadContext: dsContextHandler.ReadContext(), | ||
Schema: map[string]*schema.Schema{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This schema is identical to the resource. You may simplify this code by calling utils.ConvertSchemaFieldsToComputed
as shown here. The resource for token settings may help you simplify your code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not, is it. I mean for the resources, you have to have some four fields, the rest are optional. For datasource you have to have two fields (type, id) - but not name & document or any other field.
Simplification/re-use can still be done but I kept as-is.
cyral/utils/testutils.go
Outdated
// FormatScope formats the scope data into a string suitable for Terraform configuration. | ||
// | ||
// scope is an interface that should be a map with string keys and slice of strings as values. | ||
func FormatScope(scope interface{}) string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand that FormatPolicyIntoConfig
was put here so it can be reused for other tests, but it doesn't seem to be the case that we would reuse FormatScope
or FormatTags
, correct? If I'm correct, they could be changed to formatScope
and formatTags
/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
docs/resources/policy_v2.md
Outdated
enabled = true | ||
tags = ["finance", "global"] | ||
scope { | ||
repo_ids = ["2gaWEAyeKbETyUy1LSx985gVqrk"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please create a repo as part of the example using cyral_repository
and provide its ID from the attribute instead:
repo_ids = ["2gaWEAyeKbETyUy1LSx985gVqrk"] | |
repo_ids = [cyral_repository.myrepo.id] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
enabled = true | ||
tags = ["gym", "local"] | ||
scope { | ||
repo_ids = ["2gaWEAyeKbETyUy1LSx985gVqrk"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as previous repo comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
Not sure how we want to deprecate, tried update md file - but that is overwritten part of make targets. |
Quality Gate passedIssues Measures |
Changes I've made:
|
Description of the change
Adding terraform provider for policy v2 API:
/v2/policies
that are planned for relase inv4.15
.The resource handles policy resource life-cycle (create/update/delete and import)
The datasource handles read.
There is no TF resource that handles the filtering API (ie where you can search using posting of predicates).
Type of change
Checklists
Development
Code review
Testing
Resource, creating three policies
Datasource, read a policy
resource, update policies
Deleting the policies
Import example