From d232ccbce14db2f8f25067e13fe02b95cb7a7b32 Mon Sep 17 00:00:00 2001 From: Ruben Mennes Date: Mon, 25 Nov 2024 11:41:57 +0100 Subject: [PATCH 1/7] Grant categories data soruce --- .golangci.yml | 11 +- docs/data-sources/grant_category.md | 61 ++++ go.mod | 85 ++--- go.sum | 178 +++++----- internal/grant_category_datasource.go | 373 +++++++++++++++++++++ internal/grant_category_datasource_test.go | 35 ++ internal/provider.go | 1 + 7 files changed, 610 insertions(+), 134 deletions(-) create mode 100644 docs/data-sources/grant_category.md create mode 100644 internal/grant_category_datasource.go create mode 100644 internal/grant_category_datasource_test.go diff --git a/.golangci.yml b/.golangci.yml index cd56b36..fff4c0f 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -24,7 +24,7 @@ linters-settings: - paramTypeCombine govet: - check-shadowing: true + shadow: true revive: rules: @@ -91,6 +91,7 @@ linters: - asasalint - asciicheck - bodyclose + - copyloopvar - cyclop #- depguard #We should create a correct config to enabe depguard - dogsled @@ -101,7 +102,6 @@ linters: - errchkjson - errname - errorlint - - exportloopref - exhaustive - forbidigo - goconst @@ -144,9 +144,10 @@ run: tests: false output: - path-prefix: "" + path-prefix: '' sort-results: true - format: tab - print-issued-lines: false + formats: + - format: colored-line-number + print-issued-lines: true print-linter-name: true uniq-by-line: false \ No newline at end of file diff --git a/docs/data-sources/grant_category.md b/docs/data-sources/grant_category.md new file mode 100644 index 0000000..b2429d3 --- /dev/null +++ b/docs/data-sources/grant_category.md @@ -0,0 +1,61 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "raito_grant_category Data Source - terraform-provider-raito" +subcategory: "" +description: |- + Find a grant category by name +--- + +# raito_grant_category (Data Source) + +Find a grant category by name + + + + +## Schema + +### Required + +- `name` (String) The name of the requested grant category + +### Read-Only + +- `allow_duplicate_names` (Boolean) Indicates if duplicate names are allowed for grants of this category +- `allowed_what_items` (Attributes) Allowed WHAT items for the grant category (see [below for nested schema](#nestedatt--allowed_what_items)) +- `allowed_who_items` (Attributes) Allowed WHO items for the grant category (see [below for nested schema](#nestedatt--allowed_who_items)) +- `can_create` (Boolean) Indicates if grants of this category can be created +- `default_type_per_data_source` (Attributes Set) List of data sources and types for which the grant category is the default (see [below for nested schema](#nestedatt--default_type_per_data_source)) +- `description` (String) The description of the grant category +- `id` (String) The ID of the requested grant category +- `is_default` (Boolean) Indicates if the grant category is the default category +- `is_system` (Boolean) Indicates if the grant category is a system category +- `multi_data_source` (Boolean) Indicates if APs of this category can have multiple data sources + + +### Nested Schema for `allowed_what_items` + +Read-Only: + +- `data_object` (Boolean) Indicates if a data object is allowed as a WHAT item + + + +### Nested Schema for `allowed_who_items` + +Read-Only: + +- `categories` (Set of String) List of grant category IDs that are allowed as WHO items +- `group` (Boolean) Indicates if a group is allowed as a WHO item +- `inheritance` (Boolean) Indicates if inheritance is allowed as a WHO item +- `self` (Boolean) Indicates if self is allowed as a WHO item +- `user` (Boolean) Indicates if a user is allowed as a WHO item + + + +### Nested Schema for `default_type_per_data_source` + +Read-Only: + +- `data_source` (String) Data source ID for which the default type is the defined grant category +- `type` (String) Types for which this grant category is the default for the defined data source diff --git a/go.mod b/go.mod index 250bb67..0db7228 100644 --- a/go.mod +++ b/go.mod @@ -1,18 +1,20 @@ module github.com/raito-io/terraform-provider-raito -go 1.22 +go 1.23.0 + +toolchain go1.23.3 require ( - github.com/hashicorp/terraform-plugin-docs v0.19.4 - github.com/hashicorp/terraform-plugin-framework v1.10.0 - github.com/hashicorp/terraform-plugin-framework-jsontypes v0.1.0 - github.com/hashicorp/terraform-plugin-framework-validators v0.13.0 - github.com/hashicorp/terraform-plugin-go v0.23.0 - github.com/hashicorp/terraform-plugin-testing v1.8.0 + github.com/hashicorp/terraform-plugin-docs v0.20.0 + github.com/hashicorp/terraform-plugin-framework v1.13.0 + github.com/hashicorp/terraform-plugin-framework-jsontypes v0.2.0 + github.com/hashicorp/terraform-plugin-framework-validators v0.15.0 + github.com/hashicorp/terraform-plugin-go v0.25.0 + github.com/hashicorp/terraform-plugin-testing v1.11.0 github.com/matoous/go-nanoid/v2 v2.1.0 github.com/raito-io/enumer v0.1.4 github.com/raito-io/golang-set v0.0.4 - github.com/raito-io/sdk-go v0.0.12 + github.com/raito-io/sdk-go v0.0.13-dev0 ) require ( @@ -24,27 +26,27 @@ require ( github.com/Masterminds/sprig/v3 v3.2.3 // indirect github.com/ProtonMail/go-crypto v1.1.0-alpha.3-proton // indirect github.com/agext/levenshtein v1.2.2 // indirect - github.com/agnivade/levenshtein v1.1.1 // indirect + github.com/agnivade/levenshtein v1.2.0 // indirect github.com/alexflint/go-arg v1.5.1 // indirect github.com/alexflint/go-scalar v1.2.0 // indirect github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect github.com/armon/go-radix v1.0.0 // indirect - github.com/aws/aws-sdk-go-v2 v1.30.3 // indirect - github.com/aws/aws-sdk-go-v2/config v1.27.26 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.17.26 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect - github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.41.4 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.22.3 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.30.3 // indirect - github.com/aws/smithy-go v1.20.3 // indirect + github.com/aws/aws-sdk-go-v2 v1.32.5 // indirect + github.com/aws/aws-sdk-go-v2/config v1.28.5 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.17.46 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.20 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.24 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.24 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect + github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.47.0 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.5 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.24.6 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.5 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.33.1 // indirect + github.com/aws/smithy-go v1.22.1 // indirect github.com/bgentry/speakeasy v0.2.0 // indirect - github.com/bmatcuk/doublestar/v4 v4.6.1 // indirect + github.com/bmatcuk/doublestar/v4 v4.7.1 // indirect github.com/cloudflare/circl v1.3.9 // indirect github.com/fatih/color v1.17.0 // indirect github.com/golang/protobuf v1.5.4 // indirect @@ -57,16 +59,17 @@ require ( github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 // indirect github.com/hashicorp/go-hclog v1.6.3 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-plugin v1.6.1 // indirect + github.com/hashicorp/go-plugin v1.6.2 // indirect + github.com/hashicorp/go-retryablehttp v0.7.7 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect github.com/hashicorp/go-version v1.7.0 // indirect - github.com/hashicorp/hc-install v0.7.0 // indirect - github.com/hashicorp/hcl/v2 v2.20.1 // indirect + github.com/hashicorp/hc-install v0.9.0 // indirect + github.com/hashicorp/hcl/v2 v2.23.0 // indirect github.com/hashicorp/logutils v1.0.0 // indirect github.com/hashicorp/terraform-exec v0.21.0 // indirect - github.com/hashicorp/terraform-json v0.22.1 // indirect + github.com/hashicorp/terraform-json v0.23.0 // indirect github.com/hashicorp/terraform-plugin-log v0.9.0 // indirect - github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0 // indirect + github.com/hashicorp/terraform-plugin-sdk/v2 v2.35.0 // indirect github.com/hashicorp/terraform-registry-address v0.2.3 // indirect github.com/hashicorp/terraform-svchost v0.1.1 // indirect github.com/hashicorp/yamux v0.1.1 // indirect @@ -91,22 +94,22 @@ require ( github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect - github.com/yuin/goldmark v1.7.4 // indirect + github.com/yuin/goldmark v1.7.7 // indirect github.com/yuin/goldmark-meta v1.1.0 // indirect - github.com/zclconf/go-cty v1.14.4 // indirect + github.com/zclconf/go-cty v1.15.0 // indirect go.abhg.dev/goldmark/frontmatter v0.2.0 // indirect - golang.org/x/crypto v0.25.0 // indirect + golang.org/x/crypto v0.29.0 // indirect golang.org/x/exp v0.0.0-20240707233637-46b078467d37 // indirect - golang.org/x/mod v0.19.0 // indirect - golang.org/x/net v0.27.0 // indirect - golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.22.0 // indirect - golang.org/x/text v0.16.0 // indirect - golang.org/x/tools v0.23.0 // indirect + golang.org/x/mod v0.22.0 // indirect + golang.org/x/net v0.31.0 // indirect + golang.org/x/sync v0.9.0 // indirect + golang.org/x/sys v0.27.0 // indirect + golang.org/x/text v0.20.0 // indirect + golang.org/x/tools v0.27.0 // indirect google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240709173604-40e1e62336c5 // indirect - google.golang.org/grpc v1.65.0 // indirect - google.golang.org/protobuf v1.34.2 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect + google.golang.org/grpc v1.67.1 // indirect + google.golang.org/protobuf v1.35.1 // indirect gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index a634dbc..f0756c9 100644 --- a/go.sum +++ b/go.sum @@ -19,8 +19,8 @@ github.com/ProtonMail/go-crypto v1.1.0-alpha.3-proton h1:0RXAi0EJFs81j+MMsqvHNuA github.com/ProtonMail/go-crypto v1.1.0-alpha.3-proton/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= github.com/agext/levenshtein v1.2.2 h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXvaqE= github.com/agext/levenshtein v1.2.2/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= -github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8= -github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo= +github.com/agnivade/levenshtein v1.2.0 h1:U9L4IOT0Y3i0TIlUIDJ7rVUziKi/zPbrJGaFrtYH3SY= +github.com/agnivade/levenshtein v1.2.0/go.mod h1:QVVI16kDrtSuwcpd0p1+xMC6Z/VfhtCyDIjcwga4/DU= github.com/alexflint/go-arg v1.5.1 h1:nBuWUCpuRy0snAG+uIJ6N0UvYxpxA0/ghA/AaHxlT8Y= github.com/alexflint/go-arg v1.5.1/go.mod h1:A7vTJzvjoaSTypg4biM5uYNTkJ27SkNTArtYXnlqVO8= github.com/alexflint/go-scalar v1.2.0 h1:WR7JPKkeNpnYIOfHRa7ivM21aWAdHD0gEWHCx+WQBRw= @@ -34,38 +34,38 @@ github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/aws/aws-sdk-go-v2 v1.30.3 h1:jUeBtG0Ih+ZIFH0F4UkmL9w3cSpaMv9tYYDbzILP8dY= -github.com/aws/aws-sdk-go-v2 v1.30.3/go.mod h1:nIQjQVp5sfpQcTc9mPSr1B0PaWK5ByX9MOoDadSN4lc= -github.com/aws/aws-sdk-go-v2/config v1.27.26 h1:T1kAefbKuNum/AbShMsZEro6eRkeOT8YILfE9wyjAYQ= -github.com/aws/aws-sdk-go-v2/config v1.27.26/go.mod h1:ivWHkAWFrw/nxty5Fku7soTIVdqZaZ7dw+tc5iGW3GA= -github.com/aws/aws-sdk-go-v2/credentials v1.17.26 h1:tsm8g/nJxi8+/7XyJJcP2dLrnK/5rkFp6+i2nhmz5fk= -github.com/aws/aws-sdk-go-v2/credentials v1.17.26/go.mod h1:3vAM49zkIa3q8WT6o9Ve5Z0vdByDMwmdScO0zvThTgI= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11 h1:KreluoV8FZDEtI6Co2xuNk/UqI9iwMrOx/87PBNIKqw= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11/go.mod h1:SeSUYBLsMYFoRvHE0Tjvn7kbxaUhl75CJi1sbfhMxkU= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15 h1:SoNJ4RlFEQEbtDcCEt+QG56MY4fm4W8rYirAmq+/DdU= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15/go.mod h1:U9ke74k1n2bf+RIgoX1SXFed1HLs51OgUSs+Ph0KJP8= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15 h1:C6WHdGnTDIYETAm5iErQUiVNsclNx9qbJVPIt03B6bI= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15/go.mod h1:ZQLZqhcu+JhSrA9/NXRm8SkDvsycE+JkV3WGY41e+IM= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY= -github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.41.4 h1:jkvdmVYoVWVrAIjgt9aiR9e7GRK2DnxrMnvKjA5EJd0= -github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.41.4/go.mod h1:aynIysFCBIq18wfN2GrIYAeofOnQKV3LtkjyrQKfaFY= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3 h1:dT3MqvGhSoaIhRseqw2I0yH81l7wiR2vjs57O51EAm8= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3/go.mod h1:GlAeCkHwugxdHaueRr4nhPuY+WW+gR8UjlcqzPr1SPI= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17 h1:HGErhhrxZlQ044RiM+WdoZxp0p+EGM62y3L6pwA4olE= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17/go.mod h1:RkZEx4l0EHYDJpWppMJ3nD9wZJAa8/0lq9aVC+r2UII= -github.com/aws/aws-sdk-go-v2/service/sso v1.22.3 h1:Fv1vD2L65Jnp5QRsdiM64JvUM4Xe+E0JyVsRQKv6IeA= -github.com/aws/aws-sdk-go-v2/service/sso v1.22.3/go.mod h1:ooyCOXjvJEsUw7x+ZDHeISPMhtwI3ZCB7ggFMcFfWLU= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4 h1:yiwVzJW2ZxZTurVbYWA7QOrAaCYQR72t0wrSBfoesUE= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4/go.mod h1:0oxfLkpz3rQ/CHlx5hB7H69YUpFiI1tql6Q6Ne+1bCw= -github.com/aws/aws-sdk-go-v2/service/sts v1.30.3 h1:ZsDKRLXGWHk8WdtyYMoGNO7bTudrvuKpDKgMVRlepGE= -github.com/aws/aws-sdk-go-v2/service/sts v1.30.3/go.mod h1:zwySh8fpFyXp9yOr/KVzxOl8SRqgf/IDw5aUt9UKFcQ= -github.com/aws/smithy-go v1.20.3 h1:ryHwveWzPV5BIof6fyDvor6V3iUL7nTfiTKXHiW05nE= -github.com/aws/smithy-go v1.20.3/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E= +github.com/aws/aws-sdk-go-v2 v1.32.5 h1:U8vdWJuY7ruAkzaOdD7guwJjD06YSKmnKCJs7s3IkIo= +github.com/aws/aws-sdk-go-v2 v1.32.5/go.mod h1:P5WJBrYqqbWVaOxgH0X/FYYD47/nooaPOZPlQdmiN2U= +github.com/aws/aws-sdk-go-v2/config v1.28.5 h1:Za41twdCXbuyyWv9LndXxZZv3QhTG1DinqlFsSuvtI0= +github.com/aws/aws-sdk-go-v2/config v1.28.5/go.mod h1:4VsPbHP8JdcdUDmbTVgNL/8w9SqOkM5jyY8ljIxLO3o= +github.com/aws/aws-sdk-go-v2/credentials v1.17.46 h1:AU7RcriIo2lXjUfHFnFKYsLCwgbz1E7Mm95ieIRDNUg= +github.com/aws/aws-sdk-go-v2/credentials v1.17.46/go.mod h1:1FmYyLGL08KQXQ6mcTlifyFXfJVCNJTVGuQP4m0d/UA= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.20 h1:sDSXIrlsFSFJtWKLQS4PUWRvrT580rrnuLydJrCQ/yA= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.20/go.mod h1:WZ/c+w0ofps+/OUqMwWgnfrgzZH1DZO1RIkktICsqnY= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.24 h1:4usbeaes3yJnCFC7kfeyhkdkPtoRYPa/hTmCqMpKpLI= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.24/go.mod h1:5CI1JemjVwde8m2WG3cz23qHKPOxbpkq0HaoreEgLIY= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.24 h1:N1zsICrQglfzaBnrfM0Ys00860C+QFwu6u/5+LomP+o= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.24/go.mod h1:dCn9HbJ8+K31i8IQ8EWmWj0EiIk0+vKiHNMxTTYveAg= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= +github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.47.0 h1:9WEhV3JmFhSMnKaY2SqcPb0bM5XIoMmAy62Fj5TNMwk= +github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.47.0/go.mod h1:TxsMf+uRm3AHGUs2BSmnxz99BqUd6f9EiuDEhRppTY8= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 h1:iXtILhvDxB6kPvEXgsDhGaZCSC6LQET5ZHSdJozeI0Y= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1/go.mod h1:9nu0fVANtYiAePIBh2/pFUSwtJ402hLnp854CNoDOeE= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.5 h1:wtpJ4zcwrSbwhECWQoI/g6WM9zqCcSpHDJIWSbMLOu4= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.5/go.mod h1:qu/W9HXQbbQ4+1+JcZp0ZNPV31ym537ZJN+fiS7Ti8E= +github.com/aws/aws-sdk-go-v2/service/sso v1.24.6 h1:3zu537oLmsPfDMyjnUS2g+F2vITgy5pB74tHI+JBNoM= +github.com/aws/aws-sdk-go-v2/service/sso v1.24.6/go.mod h1:WJSZH2ZvepM6t6jwu4w/Z45Eoi75lPN7DcydSRtJg6Y= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.5 h1:K0OQAsDywb0ltlFrZm0JHPY3yZp/S9OaoLU33S7vPS8= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.5/go.mod h1:ORITg+fyuMoeiQFiVGoqB3OydVTLkClw/ljbblMq6Cc= +github.com/aws/aws-sdk-go-v2/service/sts v1.33.1 h1:6SZUVRQNvExYlMLbHdlKB48x0fLbc2iVROyaNEwBHbU= +github.com/aws/aws-sdk-go-v2/service/sts v1.33.1/go.mod h1:GqWyYCwLXnlUB1lOAXQyNSPqPLQJvmo8J0DWBzp9mtg= +github.com/aws/smithy-go v1.22.1 h1:/HPHZQ0g7f4eUeK6HKglFz8uwVfZKgoI25rb/J+dnro= +github.com/aws/smithy-go v1.22.1/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= github.com/bgentry/speakeasy v0.2.0 h1:tgObeVOf8WAvtuAX6DhJ4xks4CFNwPDZiqzGqIHE51E= github.com/bgentry/speakeasy v0.2.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bmatcuk/doublestar/v4 v4.6.1 h1:FH9SifrbvJhnlQpztAx++wlkk70QBf0iBWDwNy7PA4I= -github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= +github.com/bmatcuk/doublestar/v4 v4.7.1 h1:fdDeAqgT47acgwd9bd9HxJRDmc9UAmPpc+2m0CXv75Q= +github.com/bmatcuk/doublestar/v4 v4.7.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= github.com/bradleyjkemp/cupaloy/v2 v2.6.0 h1:knToPYa2xtfg42U3I6punFEjaGFKWQRXJwj0JTv4mTs= github.com/bradleyjkemp/cupaloy/v2 v2.6.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= @@ -77,8 +77,8 @@ github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxG github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48 h1:fRzb/w+pyskVMQ+UbP35JkH8yB7MYb4q/qhBarqZE6g= -github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= +github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54 h1:SG7nF6SRlWhcT7cNTs5R6Hk4V2lcmLz2NsG2VnInyNo= +github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= @@ -125,39 +125,41 @@ github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVH github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-plugin v1.6.1 h1:P7MR2UP6gNKGPp+y7EZw2kOiq4IR9WiqLvp0XOsVdwI= -github.com/hashicorp/go-plugin v1.6.1/go.mod h1:XPHFku2tFo3o3QKFgSYo+cghcUhw1NA1hZyMK0PWAw0= +github.com/hashicorp/go-plugin v1.6.2 h1:zdGAEd0V1lCaU0u+MxWQhtSDQmahpkwOun8U8EiRVog= +github.com/hashicorp/go-plugin v1.6.2/go.mod h1:CkgLQ5CZqNmdL9U9JzM532t8ZiYQ35+pj3b1FD37R0Q= +github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= +github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/hc-install v0.7.0 h1:Uu9edVqjKQxxuD28mR5TikkKDd/p55S8vzPC1659aBk= -github.com/hashicorp/hc-install v0.7.0/go.mod h1:ELmmzZlGnEcqoUMKUuykHaPCIR1sYLYX+KSggWSKZuA= -github.com/hashicorp/hcl/v2 v2.20.1 h1:M6hgdyz7HYt1UN9e61j+qKJBqR3orTWbI1HKBJEdxtc= -github.com/hashicorp/hcl/v2 v2.20.1/go.mod h1:TZDqQ4kNKCbh1iJp99FdPiUaVDDUPivbqxZulxDYqL4= +github.com/hashicorp/hc-install v0.9.0 h1:2dIk8LcvANwtv3QZLckxcjyF5w8KVtiMxu6G6eLhghE= +github.com/hashicorp/hc-install v0.9.0/go.mod h1:+6vOP+mf3tuGgMApVYtmsnDoKWMDcFXeTxCACYZ8SFg= +github.com/hashicorp/hcl/v2 v2.23.0 h1:Fphj1/gCylPxHutVSEOf2fBOh1VE4AuLV7+kbJf3qos= +github.com/hashicorp/hcl/v2 v2.23.0/go.mod h1:62ZYHrXgPoX8xBnzl8QzbWq4dyDsDtfCRgIq1rbJEvA= github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/terraform-exec v0.21.0 h1:uNkLAe95ey5Uux6KJdua6+cv8asgILFVWkd/RG0D2XQ= github.com/hashicorp/terraform-exec v0.21.0/go.mod h1:1PPeMYou+KDUSSeRE9szMZ/oHf4fYUmB923Wzbq1ICg= -github.com/hashicorp/terraform-json v0.22.1 h1:xft84GZR0QzjPVWs4lRUwvTcPnegqlyS7orfb5Ltvec= -github.com/hashicorp/terraform-json v0.22.1/go.mod h1:JbWSQCLFSXFFhg42T7l9iJwdGXBYV8fmmD6o/ML4p3A= -github.com/hashicorp/terraform-plugin-docs v0.19.4 h1:G3Bgo7J22OMtegIgn8Cd/CaSeyEljqjH3G39w28JK4c= -github.com/hashicorp/terraform-plugin-docs v0.19.4/go.mod h1:4pLASsatTmRynVzsjEhbXZ6s7xBlUw/2Kt0zfrq8HxA= -github.com/hashicorp/terraform-plugin-framework v1.10.0 h1:xXhICE2Fns1RYZxEQebwkB2+kXouLC932Li9qelozrc= -github.com/hashicorp/terraform-plugin-framework v1.10.0/go.mod h1:qBXLDn69kM97NNVi/MQ9qgd1uWWsVftGSnygYG1tImM= -github.com/hashicorp/terraform-plugin-framework-jsontypes v0.1.0 h1:b8vZYB/SkXJT4YPbT3trzE6oJ7dPyMy68+9dEDKsJjE= -github.com/hashicorp/terraform-plugin-framework-jsontypes v0.1.0/go.mod h1:tP9BC3icoXBz72evMS5UTFvi98CiKhPdXF6yLs1wS8A= -github.com/hashicorp/terraform-plugin-framework-validators v0.13.0 h1:bxZfGo9DIUoLLtHMElsu+zwqI4IsMZQBRRy4iLzZJ8E= -github.com/hashicorp/terraform-plugin-framework-validators v0.13.0/go.mod h1:wGeI02gEhj9nPANU62F2jCaHjXulejm/X+af4PdZaNo= -github.com/hashicorp/terraform-plugin-go v0.23.0 h1:AALVuU1gD1kPb48aPQUjug9Ir/125t+AAurhqphJ2Co= -github.com/hashicorp/terraform-plugin-go v0.23.0/go.mod h1:1E3Cr9h2vMlahWMbsSEcNrOCxovCZhOOIXjFHbjc/lQ= +github.com/hashicorp/terraform-json v0.23.0 h1:sniCkExU4iKtTADReHzACkk8fnpQXrdD2xoR+lppBkI= +github.com/hashicorp/terraform-json v0.23.0/go.mod h1:MHdXbBAbSg0GvzuWazEGKAn/cyNfIB7mN6y7KJN6y2c= +github.com/hashicorp/terraform-plugin-docs v0.20.0 h1:ox7rm1FN0dVZaJBUzkVVh10R1r3+FeMQWL0QopQ9d7o= +github.com/hashicorp/terraform-plugin-docs v0.20.0/go.mod h1:A/+4SVMdAkQYtIBtaxV0H7AU862TxVZk/hhKaMDQB6Y= +github.com/hashicorp/terraform-plugin-framework v1.13.0 h1:8OTG4+oZUfKgnfTdPTJwZ532Bh2BobF4H+yBiYJ/scw= +github.com/hashicorp/terraform-plugin-framework v1.13.0/go.mod h1:j64rwMGpgM3NYXTKuxrCnyubQb/4VKldEKlcG8cvmjU= +github.com/hashicorp/terraform-plugin-framework-jsontypes v0.2.0 h1:SJXL5FfJJm17554Kpt9jFXngdM6fXbnUnZ6iT2IeiYA= +github.com/hashicorp/terraform-plugin-framework-jsontypes v0.2.0/go.mod h1:p0phD0IYhsu9bR4+6OetVvvH59I6LwjXGnTVEr8ox6E= +github.com/hashicorp/terraform-plugin-framework-validators v0.15.0 h1:RXMmu7JgpFjnI1a5QjMCBb11usrW2OtAG+iOTIj5c9Y= +github.com/hashicorp/terraform-plugin-framework-validators v0.15.0/go.mod h1:Bh89/hNmqsEWug4/XWKYBwtnw3tbz5BAy1L1OgvbIaY= +github.com/hashicorp/terraform-plugin-go v0.25.0 h1:oi13cx7xXA6QciMcpcFi/rwA974rdTxjqEhXJjbAyks= +github.com/hashicorp/terraform-plugin-go v0.25.0/go.mod h1:+SYagMYadJP86Kvn+TGeV+ofr/R3g4/If0O5sO96MVw= github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0= github.com/hashicorp/terraform-plugin-log v0.9.0/go.mod h1:rKL8egZQ/eXSyDqzLUuwUYLVdlYeamldAHSxjUFADow= -github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0 h1:qHprzXy/As0rxedphECBEQAh3R4yp6pKksKHcqZx5G8= -github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0/go.mod h1:H+8tjs9TjV2w57QFVSMBQacf8k/E1XwLXGCARgViC6A= -github.com/hashicorp/terraform-plugin-testing v1.8.0 h1:wdYIgwDk4iO933gC4S8KbKdnMQShu6BXuZQPScmHvpk= -github.com/hashicorp/terraform-plugin-testing v1.8.0/go.mod h1:o2kOgf18ADUaZGhtOl0YCkfIxg01MAiMATT2EtIHlZk= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.35.0 h1:wyKCCtn6pBBL46c1uIIBNUOWlNfYXfXpVo16iDyLp8Y= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.35.0/go.mod h1:B0Al8NyYVr8Mp/KLwssKXG1RqnTk7FySqSn4fRuLNgw= +github.com/hashicorp/terraform-plugin-testing v1.11.0 h1:MeDT5W3YHbONJt2aPQyaBsgQeAIckwPX41EUHXEn29A= +github.com/hashicorp/terraform-plugin-testing v1.11.0/go.mod h1:WNAHQ3DcgV/0J+B15WTE6hDvxcUdkPPpnB1FR3M910U= github.com/hashicorp/terraform-registry-address v0.2.3 h1:2TAiKJ1A3MAkZlH1YI/aTVcLZRu7JseiXNRHbOAyoTI= github.com/hashicorp/terraform-registry-address v0.2.3/go.mod h1:lFHA76T8jfQteVfT7caREqguFrW3c4MFSPhZB7HHgUM= github.com/hashicorp/terraform-svchost v0.1.1 h1:EZZimZ1GxdqFRinZ1tpJwVxxt49xc/S52uzrw4x0jKQ= @@ -224,13 +226,13 @@ github.com/raito-io/enumer v0.1.4 h1:r2QqGMjfKwn+yMHo4ybOAWvYON4pLBy+ucVP5niyHK4 github.com/raito-io/enumer v0.1.4/go.mod h1:+tSaVlYRuVnf2vA7ETf8t7/Mzq/sgvWT/dHeMVOjBu8= github.com/raito-io/golang-set v0.0.4 h1:7zk8r1TCE/F9JOOgseIXYx7oZJdC9/j5uivkCYjnCg0= github.com/raito-io/golang-set v0.0.4/go.mod h1:ktKACNnQeSpzo0Nes6jDTs74UOau8psJpAesatiEKQE= -github.com/raito-io/sdk-go v0.0.12 h1:X8xXQKbS0UPgr1W5PON6qkBs84+3B9F6RZhLoeC1kZQ= -github.com/raito-io/sdk-go v0.0.12/go.mod h1:9HI97cz4LIeHIt88GGzmVySzh44xidQcD1yyYmLDCXw= +github.com/raito-io/sdk-go v0.0.13-dev0 h1:kdjyMSzMW5bd8OkbUF6BOJbzlI1R8gz8iz9Y0GXZqKU= +github.com/raito-io/sdk-go v0.0.13-dev0/go.mod h1:w09xEXbcxbtMCY4jGWwPsP7TLLlYM5HKHh8M/T7UlH8= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= @@ -246,8 +248,8 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/vektah/gqlparser/v2 v2.5.16 h1:1gcmLTvs3JLKXckwCwlUagVn/IlV2bwqle0vJ0vy5p8= github.com/vektah/gqlparser/v2 v2.5.16/go.mod h1:1lz1OeCqgQbQepsGxPVywrjdBHW2T08PUS3pJqepRww= github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= @@ -260,38 +262,38 @@ github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/yuin/goldmark v1.7.4 h1:BDXOHExt+A7gwPCJgPIIq7ENvceR7we7rOS9TNoLZeg= -github.com/yuin/goldmark v1.7.4/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= +github.com/yuin/goldmark v1.7.7 h1:5m9rrB1sW3JUMToKFQfb+FGt1U7r57IHu5GrYrG2nqU= +github.com/yuin/goldmark v1.7.7/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= github.com/yuin/goldmark-meta v1.1.0 h1:pWw+JLHGZe8Rk0EGsMVssiNb/AaPMHfSRszZeUeiOUc= github.com/yuin/goldmark-meta v1.1.0/go.mod h1:U4spWENafuA7Zyg+Lj5RqK/MF+ovMYtBvXi1lBb2VP0= -github.com/zclconf/go-cty v1.14.4 h1:uXXczd9QDGsgu0i/QFR/hzI5NYCHLf6NQw/atrbnhq8= -github.com/zclconf/go-cty v1.14.4/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= -github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b h1:FosyBZYxY34Wul7O/MSKey3txpPYyCqVO5ZyceuQJEI= -github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8= +github.com/zclconf/go-cty v1.15.0 h1:tTCRWxsexYUmtt/wVxgDClUe+uQusuI443uL6e+5sXQ= +github.com/zclconf/go-cty v1.15.0/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= +github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo= +github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM= go.abhg.dev/goldmark/frontmatter v0.2.0 h1:P8kPG0YkL12+aYk2yU3xHv4tcXzeVnN+gU0tJ5JnxRw= go.abhg.dev/goldmark/frontmatter v0.2.0/go.mod h1:XqrEkZuM57djk7zrlRUB02x8I5J0px76YjkOzhB4YlU= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= -golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= -golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= +golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= +golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= golang.org/x/exp v0.0.0-20240707233637-46b078467d37 h1:uLDX+AfeFCct3a2C7uIWBKMJIR3CJMhcgfrUAqjRK6w= golang.org/x/exp v0.0.0-20240707233637-46b078467d37/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= -golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= +golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= +golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= +golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -305,8 +307,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= +golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= @@ -316,26 +318,26 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= -golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= +golang.org/x/tools v0.27.0 h1:qEKojBykQkQ4EynWy4S8Weg69NumxKdn40Fce3uc/8o= +golang.org/x/tools v0.27.0/go.mod h1:sUi0ZgbwW9ZPAq26Ekut+weQPR5eIM6GQLQ1Yjm1H0Q= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240709173604-40e1e62336c5 h1:SbSDUWW1PAO24TNpLdeheoYPd7kllICcLU52x6eD4kQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240709173604-40e1e62336c5/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= -google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= -google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 h1:e7S5W7MGGLaSu8j3YjdezkZ+m1/Nm0uRVRMEMGk26Xs= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= diff --git a/internal/grant_category_datasource.go b/internal/grant_category_datasource.go new file mode 100644 index 0000000..a59a343 --- /dev/null +++ b/internal/grant_category_datasource.go @@ -0,0 +1,373 @@ +package internal + +import ( + "context" + "fmt" + + "github.com/hashicorp/terraform-plugin-framework/attr" + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/raito-io/sdk-go" + types2 "github.com/raito-io/sdk-go/types" +) + +var _ datasource.DataSource = (*GrantCategoryDataSource)(nil) + +type GrantCategoryDataSourceModel struct { + Id types.String `tfsdk:"id"` + Name types.String `tfsdk:"name"` + Description types.String `tfsdk:"description"` + IsSystem types.Bool `tfsdk:"is_system"` + IsDefault types.Bool `tfsdk:"is_default"` + CanCreate types.Bool `tfsdk:"can_create"` + AllowDuplicateNames types.Bool `tfsdk:"allow_duplicate_names"` + MultiDataSource types.Bool `tfsdk:"multi_data_source"` + DefaultTypePerDataSource types.Set `tfsdk:"default_type_per_data_source"` + AllowedWhoItems types.Object `tfsdk:"allowed_who_items"` + AllowedWhatItems types.Object `tfsdk:"allowed_what_items"` +} + +type GrantCategoryDataSource struct { + client *sdk.RaitoClient +} + +func NewGrantCategoryDataSource() datasource.DataSource { + return &GrantCategoryDataSource{} +} + +func (g *GrantCategoryDataSource) Metadata(_ context.Context, request datasource.MetadataRequest, response *datasource.MetadataResponse) { + response.TypeName = request.ProviderTypeName + "_grant_category" +} + +func (g *GrantCategoryDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, response *datasource.SchemaResponse) { + response.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ + Required: false, + Optional: false, + Computed: true, + Sensitive: false, + Description: "The ID of the requested grant category", + MarkdownDescription: "The ID of the requested grant category", + }, + "name": schema.StringAttribute{ + Required: true, + Optional: false, + Computed: false, + Sensitive: false, + Description: "The name of the requested grant category", + MarkdownDescription: "The name of the requested grant category", + }, + "description": schema.StringAttribute{ + Required: false, + Optional: false, + Computed: true, + Sensitive: false, + Description: "The description of the grant category", + MarkdownDescription: "The description of the grant category", + }, + "is_system": schema.BoolAttribute{ + Required: false, + Optional: false, + Computed: true, + Sensitive: false, + Description: "Indicates if the grant category is a system category", + MarkdownDescription: "Indicates if the grant category is a system category", + }, + "is_default": schema.BoolAttribute{ + Required: false, + Optional: false, + Computed: true, + Sensitive: false, + Description: "Indicates if the grant category is the default category", + MarkdownDescription: "Indicates if the grant category is the default category", + }, + "can_create": schema.BoolAttribute{ + Required: false, + Optional: false, + Computed: true, + Sensitive: false, + Description: "Indicates if grants of this category can be created", + MarkdownDescription: "Indicates if grants of this category can be created", + }, + "allow_duplicate_names": schema.BoolAttribute{ + Required: false, + Optional: false, + Computed: true, + Sensitive: false, + Description: "Indicates if duplicate names are allowed for grants of this category", + MarkdownDescription: "Indicates if duplicate names are allowed for grants of this category", + }, + "multi_data_source": schema.BoolAttribute{ + Required: false, + Optional: false, + Computed: true, + Sensitive: false, + Description: "Indicates if APs of this category can have multiple data sources", + MarkdownDescription: "Indicates if APs of this category can have multiple data sources", + }, + "default_type_per_data_source": schema.SetNestedAttribute{ + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "data_source": schema.StringAttribute{ + Required: false, + Optional: false, + Computed: true, + Sensitive: false, + Description: "Data source ID for which the default type is the defined grant category", + MarkdownDescription: "Data source ID for which the default type is the defined grant category", + }, + "type": schema.StringAttribute{ + Required: false, + Optional: false, + Computed: true, + Sensitive: false, + Description: "Types for which this grant category is the default for the defined data source", + MarkdownDescription: "Types for which this grant category is the default for the defined data source", + }, + }, + }, + Required: false, + Optional: false, + Computed: true, + Sensitive: false, + Description: "List of data sources and types for which the grant category is the default", + MarkdownDescription: "List of data sources and types for which the grant category is the default", + }, + "allowed_who_items": schema.SingleNestedAttribute{ + Attributes: map[string]schema.Attribute{ + "user": schema.BoolAttribute{ + Required: false, + Optional: false, + Computed: true, + Sensitive: false, + Description: "Indicates if a user is allowed as a WHO item", + MarkdownDescription: "Indicates if a user is allowed as a WHO item", + }, + "group": schema.BoolAttribute{ + Required: false, + Optional: false, + Computed: true, + Sensitive: false, + Description: "Indicates if a group is allowed as a WHO item", + MarkdownDescription: "Indicates if a group is allowed as a WHO item", + }, + "inheritance": schema.BoolAttribute{ + Required: false, + Optional: false, + Computed: true, + Sensitive: false, + Description: "Indicates if inheritance is allowed as a WHO item", + MarkdownDescription: "Indicates if inheritance is allowed as a WHO item", + }, + "self": schema.BoolAttribute{ + Required: false, + Optional: false, + Computed: true, + Sensitive: false, + Description: "Indicates if self is allowed as a WHO item", + MarkdownDescription: "Indicates if self is allowed as a WHO item", + }, + "categories": schema.SetAttribute{ + ElementType: types.StringType, + Required: false, + Optional: false, + Computed: true, + Sensitive: false, + Description: "List of grant category IDs that are allowed as WHO items", + MarkdownDescription: "List of grant category IDs that are allowed as WHO items", + }, + }, + Required: false, + Optional: false, + Computed: true, + Sensitive: false, + Description: "Allowed WHO items for the grant category", + MarkdownDescription: "Allowed WHO items for the grant category", + }, + "allowed_what_items": schema.SingleNestedAttribute{ + Attributes: map[string]schema.Attribute{ + "data_object": schema.BoolAttribute{ + Required: false, + Optional: false, + Computed: true, + Sensitive: false, + Description: "Indicates if a data object is allowed as a WHAT item", + MarkdownDescription: "Indicates if a data object is allowed as a WHAT item", + }, + }, + Required: false, + Optional: false, + Computed: true, + Sensitive: false, + Description: "Allowed WHAT items for the grant category", + MarkdownDescription: "Allowed WHAT items for the grant category", + }, + }, + Description: "Find a grant category by name", + MarkdownDescription: "Find a grant category by name", + } +} + +func (g *GrantCategoryDataSource) Read(ctx context.Context, request datasource.ReadRequest, response *datasource.ReadResponse) { + var data GrantCategoryDataSourceModel + + response.Diagnostics.Append(request.Config.Get(ctx, &data)...) + + if response.Diagnostics.HasError() { + return + } + + name := data.Name.ValueString() + + grantCategories, err := g.client.GrantCategory().ListGrantCategories(ctx) + if err != nil { + response.Diagnostics.AddError("failed to list grant categories", err.Error()) + + return + } + + for i := range grantCategories { + if grantCategories[i].Name == name { + setGrantCategoryData(&grantCategories[i], &data, response.Diagnostics) + + if response.Diagnostics.HasError() { + return + } + + response.Diagnostics.Append(response.State.Set(ctx, data)...) + + return + } + } + + response.Diagnostics.AddError("grant category not found", "grant category not found") +} + +func (g *GrantCategoryDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { + if req.ProviderData == nil { + return + } + + client, ok := req.ProviderData.(*sdk.RaitoClient) + if !ok { + resp.Diagnostics.AddError( + "Unexpected Resource Configure Type", + fmt.Sprintf("Expected *sdk.RaitoClient, got: %T. Please report this issue to the provider developers.", req.ProviderData), + ) + + return + } + + if client == nil { + resp.Diagnostics.AddError( + "Unexpected Resource Configure Type", + "Expected *sdk.RaitoClient, not to be nil.", + ) + + return + } + + g.client = client +} + +func setGrantCategoryData(data *types2.GrantCategoryDetails, resp *GrantCategoryDataSourceModel, diagnostic diag.Diagnostics) { + resp.Id = types.StringValue(data.Id) + resp.Description = types.StringValue(data.Description) + resp.IsSystem = types.BoolValue(data.IsSystem) + resp.IsDefault = types.BoolValue(data.IsDefault) + resp.CanCreate = types.BoolValue(data.CanCreate) + resp.AllowDuplicateNames = types.BoolValue(data.AllowDuplicateNames) + resp.MultiDataSource = types.BoolValue(data.MultiDataSource) + + // Default types per DS + defaultTypesPerDs := make([]attr.Value, 0, len(data.DefaultTypePerDataSource)) + + for _, v := range data.DefaultTypePerDataSource { + objectValue, diags := types.ObjectValue(map[string]attr.Type{ + "data_source": types.StringType, + "type": types.StringType, + }, + map[string]attr.Value{ + "data_source": types.StringValue(v.GetDataSource()), + "type": types.StringValue(v.GetType()), + }) + + diagnostic.Append(diags...) + + if diagnostic.HasError() { + return + } + + defaultTypesPerDs = append(defaultTypesPerDs, objectValue) + } + + defaultTypesPerDsAttr, diags := types.SetValue(types.ObjectType{}, defaultTypesPerDs) + + diagnostic.Append(diags...) + + if diagnostic.HasError() { + return + } + + resp.DefaultTypePerDataSource = defaultTypesPerDsAttr + + // Allowed WHO items + whoCategoryValues := make([]attr.Value, 0, len(data.AllowedWhoItems.Categories)) + for _, v := range data.AllowedWhoItems.Categories { + whoCategoryValues = append(whoCategoryValues, types.StringValue(v)) + } + + whoCategories, diags := types.SetValue(types.StringType, whoCategoryValues) + + diagnostic.Append(diags...) + + if diagnostic.HasError() { + return + } + + allowedWhoItems, diags := types.ObjectValue( + map[string]attr.Type{ + "user": types.BoolType, + "group": types.BoolType, + "inheritance": types.BoolType, + "self": types.BoolType, + "categories": types.SetType{ElemType: types.StringType}, + }, + map[string]attr.Value{ + "user": types.BoolValue(data.AllowedWhoItems.User), + "group": types.BoolValue(data.AllowedWhoItems.Group), + "inheritance": types.BoolValue(data.AllowedWhoItems.Inheritance), + "self": types.BoolValue(data.AllowedWhoItems.Self), + "categories": whoCategories, + }, + ) + + diagnostic.Append(diags...) + + if diagnostic.HasError() { + return + } + + resp.AllowedWhoItems = allowedWhoItems + + // Allowed WHAT items + allowedWhatItems, diags := types.ObjectValue( + map[string]attr.Type{ + "data_object": types.BoolType, + }, + map[string]attr.Value{ + "data_object": types.BoolValue(data.AllowedWhatItems.DataObject), + }, + ) + + diagnostic.Append(diags...) + + if diagnostic.HasError() { + return + } + + resp.AllowedWhatItems = allowedWhatItems +} diff --git a/internal/grant_category_datasource_test.go b/internal/grant_category_datasource_test.go new file mode 100644 index 0000000..947777d --- /dev/null +++ b/internal/grant_category_datasource_test.go @@ -0,0 +1,35 @@ +package internal + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/tfversion" +) + +func TestAccGrantCategoryDataSource(t *testing.T) { + t.Run("Existing purpose", func(t *testing.T) { + resource.Test(t, resource.TestCase{ + IsUnitTest: false, + PreCheck: func() { + AccProviderPreCheck(t) + }, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_0_0), + }, + Steps: []resource.TestStep{ + { + Config: providerConfig + ` +data "raito_grant_category" "test" { + name = "Purpose" +} + `, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.raito_grant_category.test", "name", "Purpose"), + resource.TestCheckResourceAttr("data.raito_grant_category.test", "is_system", "true"), + ), + }, + }, + }) + }) +} diff --git a/internal/provider.go b/internal/provider.go index 6c6ca42..bab8095 100644 --- a/internal/provider.go +++ b/internal/provider.go @@ -106,6 +106,7 @@ func (p *RaitoCloudProvider) Resources(_ context.Context) []func() resource.Reso func (p *RaitoCloudProvider) DataSources(_ context.Context) []func() datasource.DataSource { return []func() datasource.DataSource{ NewDataSourceDataSource, + NewGrantCategoryDataSource, NewUserDataSource, } } From 216ebf1c52c6ef4155897fe44315e92a235ce2ba Mon Sep 17 00:00:00 2001 From: Ruben Mennes Date: Mon, 25 Nov 2024 11:43:27 +0100 Subject: [PATCH 2/7] Start testing from terraform version 1.5 --- .github/workflows/test.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9191255..66d18bd 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -67,14 +67,12 @@ jobs: matrix: # list whatever Terraform versions here you would like to support terraform: - - '1.1.*' - - '1.2.*' - - '1.3.*' - - '1.4.*' - '1.5.*' - '1.6.*' - '1.7.*' - '1.8.*' + - '1.9.*' + - '1.10.*' steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 From d1b163e69726a3dfed1cd1ff7786cb021cd8c83c Mon Sep 17 00:00:00 2001 From: Ruben Mennes Date: Mon, 25 Nov 2024 11:57:29 +0100 Subject: [PATCH 3/7] Update test grant category data source --- internal/grant_category_datasource.go | 7 +++- internal/grant_category_datasource_test.go | 41 ++++++++++++---------- 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/internal/grant_category_datasource.go b/internal/grant_category_datasource.go index a59a343..3fb9897 100644 --- a/internal/grant_category_datasource.go +++ b/internal/grant_category_datasource.go @@ -304,7 +304,12 @@ func setGrantCategoryData(data *types2.GrantCategoryDetails, resp *GrantCategory defaultTypesPerDs = append(defaultTypesPerDs, objectValue) } - defaultTypesPerDsAttr, diags := types.SetValue(types.ObjectType{}, defaultTypesPerDs) + defaultTypesPerDsAttr, diags := types.SetValue(types.ObjectType{ + AttrTypes: map[string]attr.Type{ + "data_source": types.StringType, + "type": types.StringType, + }, + }, defaultTypesPerDs) diagnostic.Append(diags...) diff --git a/internal/grant_category_datasource_test.go b/internal/grant_category_datasource_test.go index 947777d..db5e420 100644 --- a/internal/grant_category_datasource_test.go +++ b/internal/grant_category_datasource_test.go @@ -8,28 +8,33 @@ import ( ) func TestAccGrantCategoryDataSource(t *testing.T) { - t.Run("Existing purpose", func(t *testing.T) { - resource.Test(t, resource.TestCase{ - IsUnitTest: false, - PreCheck: func() { - AccProviderPreCheck(t) - }, - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_0_0), - }, - Steps: []resource.TestStep{ - { - Config: providerConfig + ` + resource.Test(t, resource.TestCase{ + IsUnitTest: false, + PreCheck: func() { + AccProviderPreCheck(t) + }, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_0_0), + }, + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + Steps: []resource.TestStep{ + { + Config: providerConfig + ` data "raito_grant_category" "test" { name = "Purpose" } `, - Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr("data.raito_grant_category.test", "name", "Purpose"), - resource.TestCheckResourceAttr("data.raito_grant_category.test", "is_system", "true"), - ), - }, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.raito_grant_category.test", "id", "purpose"), + resource.TestCheckResourceAttr("data.raito_grant_category.test", "name", "Purpose"), + resource.TestCheckResourceAttr("data.raito_grant_category.test", "is_system", "false"), + resource.TestCheckResourceAttr("data.raito_grant_category.test", "is_default", "false"), + resource.TestCheckResourceAttr("data.raito_grant_category.test", "can_create", "true"), + resource.TestCheckResourceAttr("data.raito_grant_category.test", "allow_duplicate_names", "true"), + resource.TestCheckResourceAttr("data.raito_grant_category.test", "default_type_per_data_source.#", "0"), + ), }, - }) + }, }) + } From 07b911b46ad25ba725e903510310137c225a0fdf Mon Sep 17 00:00:00 2001 From: Ruben Mennes Date: Tue, 10 Dec 2024 09:25:46 +0100 Subject: [PATCH 4/7] Grant categories in grant resources --- docs/data-sources/grant_category.md | 6 + docs/resources/grant.md | 38 +- docs/resources/grant_category.md | 105 ++++ docs/resources/purpose.md | 81 --- .../raito_grant_category/data-source.tf | 3 + examples/resources/raito_grant/resource.tf | 19 +- .../resources/raito_grant_category/import.sh | 2 + .../raito_grant_category/resource.tf | 28 + examples/resources/raito_purpose/import.sh | 2 - examples/resources/raito_purpose/resource.tf | 25 - go.mod | 24 +- go.sum | 48 +- internal/grant_category_resource.go | 558 ++++++++++++++++++ internal/grant_category_resource_test.go | 90 +++ internal/grant_resource.go | 140 ++++- internal/grant_resource_test.go | 136 ++++- internal/provider.go | 2 +- internal/purpose_resource.go | 111 ---- internal/purpose_resource_test.go | 175 ------ 19 files changed, 1087 insertions(+), 506 deletions(-) create mode 100644 docs/resources/grant_category.md delete mode 100644 docs/resources/purpose.md create mode 100644 examples/data-sources/raito_grant_category/data-source.tf create mode 100644 examples/resources/raito_grant_category/import.sh create mode 100644 examples/resources/raito_grant_category/resource.tf delete mode 100644 examples/resources/raito_purpose/import.sh delete mode 100644 examples/resources/raito_purpose/resource.tf create mode 100644 internal/grant_category_resource.go create mode 100644 internal/grant_category_resource_test.go delete mode 100644 internal/purpose_resource.go delete mode 100644 internal/purpose_resource_test.go diff --git a/docs/data-sources/grant_category.md b/docs/data-sources/grant_category.md index b2429d3..26ba774 100644 --- a/docs/data-sources/grant_category.md +++ b/docs/data-sources/grant_category.md @@ -10,7 +10,13 @@ description: |- Find a grant category by name +## Example Usage +```terraform +data "raito_grant_category" "example" { + name = "Purpose" +} +``` ## Schema diff --git a/docs/resources/grant.md b/docs/resources/grant.md index 137f459..1e2a90e 100644 --- a/docs/resources/grant.md +++ b/docs/resources/grant.md @@ -30,8 +30,13 @@ resource "raito_grant" "grant1" { promise_duration : 604800 } ] - type = "role" - data_source = raito_datasource.ds.id + type = "role" + data_source = [ + { + data_source : raito_datasource.ds.id + type : "role" + } + ] what_data_objects = { data_object : [ { @@ -47,16 +52,22 @@ resource "raito_grant" "grant1" { } } -resource "raito_grant" "grant2" { +resource "raito_grant" "grant_purpose1" { name = "Grant2" description = "Grant with inherited who" + category = "purpose" state = "Active" who = [ { access_control = raito_grant.grant1.id } ] - data_source = raito_datasource.ds.id + data_source = [ + { + data_source : raito_datasource.ds.id + type : "role" + } + ] } ``` @@ -65,16 +76,16 @@ resource "raito_grant" "grant2" { ### Required -- `data_source` (String) The ID of the data source of the grant +- `data_source` (Attributes Set) The ID of the data source of the grant (see [below for nested schema](#nestedatt--data_source)) - `name` (String) The name of the grant ### Optional +- `category` (String) The ID of the category of the grant - `description` (String) The description of the grant - `inheritance_locked` (Boolean) Indicates if who should be locked. This should be true if who access providers are set. - `owners` (Set of String) User id of the owners of this grant - `state` (String) The state of the grant Possible values are: ["Active", "Inactive"] -- `type` (String) The type of the grant - `what_abac_rule` (Attributes) What data object defined by abac rule. Cannot be set when what_data_objects is set. (see [below for nested schema](#nestedatt--what_abac_rule)) - `what_data_objects` (Attributes Set) The data object what items associated to the grant. When this is not set (nil), the what list will not be overridden. This is typically used when this should be managed from Raito Cloud. (see [below for nested schema](#nestedatt--what_data_objects)) - `what_locked` (Boolean) Indicates whether it should lock the what. Should be set to true if what_data_objects or what_abac_rule is set. @@ -86,6 +97,18 @@ resource "raito_grant" "grant2" { - `id` (String) The ID of the grant + +### Nested Schema for `data_source` + +Required: + +- `data_source` (String) The ID of the data source of the grant + +Optional: + +- `type` (String) The implementation type of the grant for this data source + + ### Nested Schema for `what_abac_rule` @@ -93,12 +116,12 @@ Required: - `do_types` (Set of String) Set of data object types associated to the abac rule - `rule` (String) json representation of the abac rule +- `scope` (Set of String) Scope of the defined abac rule Optional: - `global_permissions` (Set of String) Set of global permissions that should be granted on the matching data object. Allowed values are [READ WRITE ADMIN] - `permissions` (Set of String) Set of permissions that should be granted on the matching data object -- `scope` (Set of String) Scope of the defined abac rule @@ -106,6 +129,7 @@ Optional: Required: +- `data_source` (String) The data source of the data object - `fullname` (String) The full name of the data object in the data source Optional: diff --git a/docs/resources/grant_category.md b/docs/resources/grant_category.md new file mode 100644 index 0000000..14dfabd --- /dev/null +++ b/docs/resources/grant_category.md @@ -0,0 +1,105 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "raito_grant_category Resource - terraform-provider-raito" +subcategory: "" +description: |- + The grant category resource allows you to manage grant categories in Raito. +--- + +# raito_grant_category (Resource) + +The grant category resource allows you to manage grant categories in Raito. + +## Example Usage + +```terraform +resource "raito_datasource" "ds" { + name = "exampleDS" +} + +resource "raito_grant_category" "example_category" { + name = "exampleCategory" + description = "A simple category" + icon = "testIcon" + can_create = true + allow_duplicated_names = true + multi_data_source = true + default_type_per_data_source = [ + { + data_source : raito_datasource.ds.id + type : "table" + } + ] + allowed_who_items = { + user = true + group = true + inheritance = true + self = true + categories = ["otherCategoryId"] + } + allowed_what_items = { + data_object = true + } +} +``` + + +## Schema + +### Required + +- `icon` (String) The icon of the grant category +- `name` (String) The name of the grant category + +### Optional + +- `allow_duplicate_names` (Boolean) Whether the user can create grants with duplicate names in this category +- `allowed_what_items` (Attributes) The allowed WHAT items for the grants of this category (see [below for nested schema](#nestedatt--allowed_what_items)) +- `allowed_who_items` (Attributes) The allowed WHO items for the grants of this category (see [below for nested schema](#nestedatt--allowed_who_items)) +- `can_create` (Boolean) Whether the user can create grants in this category +- `default_type_per_data_source` (Attributes Set) The default category for each data source, type pair (see [below for nested schema](#nestedatt--default_type_per_data_source)) +- `description` (String) The description of the grant category +- `multi_data_source` (Boolean) Whether the grant category supports multiple data sources + +### Read-Only + +- `id` (String) The ID of the grant category +- `is_default` (Boolean) Whether the grant category is a default category +- `is_system` (Boolean) Whether the grant category is a system category + + +### Nested Schema for `allowed_what_items` + +Optional: + +- `data_object` (Boolean) The allowed WHAT items for the grants of this category + + + +### Nested Schema for `allowed_who_items` + +Optional: + +- `categories` (Set of String) The allowed WHO items for the grants of this category +- `group` (Boolean) Whether the group is allowed as WHO item for the grants of this category +- `inheritance` (Boolean) Whether the inheritance is allowed as WHO item for the grants of this category +- `self` (Boolean) Whether the self is allowed as WHO item for the grants of this category +- `user` (Boolean) Whether the user is allowed as WHO item for the grants of this category + + + +### Nested Schema for `default_type_per_data_source` + +Required: + +- `data_source` (String) The data source for which the default type is set +- `type` (String) The default type for the data source + +## Import + +Import is supported using the following syntax: + +```shell +#Import grant. Not that who and what_data_objects will not be imported +terraform import raito_grant_category.example GrantCategoryId +``` diff --git a/docs/resources/purpose.md b/docs/resources/purpose.md deleted file mode 100644 index 3c92abe..0000000 --- a/docs/resources/purpose.md +++ /dev/null @@ -1,81 +0,0 @@ ---- -# generated by https://github.com/hashicorp/terraform-plugin-docs -page_title: "raito_purpose Resource - terraform-provider-raito" -subcategory: "" -description: |- - The resource for representing a Raito Purpose https://docs.raito.io/docs/cloud/access_management/purposes access control. ---- - -# raito_purpose (Resource) - -The resource for representing a Raito [Purpose](https://docs.raito.io/docs/cloud/access_management/purposes) access control. - -## Example Usage - -```terraform -resource "raito_datasource" "ds" { - name = "exampleDS" -} - -resource "raito_grant" "grant1" { - name = "An existing grant" -} - -resource "raito_purpose" "example_purpose" { - name = "Example Purpose" - description = "This is an example purpose" - state = "Inactive" - what = [ - raito_grant.grant1.id - ] - who = [ - { - user = "user1@company.com" - }, - { - user = "user2@company.com", - promise_duration : 604800 - } - ] -} -``` - - -## Schema - -### Required - -- `name` (String) The name of the purpose - -### Optional - -- `description` (String) The description of the purpose -- `inheritance_locked` (Boolean) Indicates if who should be locked. This should be true if who access providers are set. -- `owners` (Set of String) User id of the owners of this purpose -- `state` (String) The state of the purpose Possible values are: ["Active", "Inactive"] -- `who` (Attributes Set) The who-items associated with the purpose. When this is not set (nil), the who-list will not be overridden. This is typically used when this should be managed from Raito Cloud. (see [below for nested schema](#nestedatt--who)) -- `who_abac_rule` (String) json representation of the abac rule for who-items associated with the purpose -- `who_locked` (Boolean) Indicates if who should be locked. This should be true if who users, who groups, or who_abac_rule is set. - -### Read-Only - -- `id` (String) The ID of the purpose - - -### Nested Schema for `who` - -Optional: - -- `access_control` (String) The ID of the access control in Raito Cloud. Cannot be set if `user` or `group` is set. -- `group` (String) The ID of the group in Raito Cloud. This cannot be set if `user` or `access_control` is set. -- `promise_duration` (Number) Specify this to indicate that this who-item is a promise instead of a direct grant. This is specified as the number of seconds that access should be granted when requested. -- `user` (String) The email address of the user. This cannot be set if `group` or `access_control` is set. - -## Import - -Import is supported using the following syntax: - -```shell -#Import purpose. Not that who and what will not be imported -terraform import raito_purpose.example PurposeId -``` diff --git a/examples/data-sources/raito_grant_category/data-source.tf b/examples/data-sources/raito_grant_category/data-source.tf new file mode 100644 index 0000000..522e403 --- /dev/null +++ b/examples/data-sources/raito_grant_category/data-source.tf @@ -0,0 +1,3 @@ +data "raito_grant_category" "example" { + name = "Purpose" +} \ No newline at end of file diff --git a/examples/resources/raito_grant/resource.tf b/examples/resources/raito_grant/resource.tf index 04521c2..235c14c 100644 --- a/examples/resources/raito_grant/resource.tf +++ b/examples/resources/raito_grant/resource.tf @@ -15,8 +15,13 @@ resource "raito_grant" "grant1" { promise_duration : 604800 } ] - type = "role" - data_source = raito_datasource.ds.id + type = "role" + data_source = [ + { + data_source : raito_datasource.ds.id + type : "role" + } + ] what_data_objects = { data_object : [ { @@ -32,14 +37,20 @@ resource "raito_grant" "grant1" { } } -resource "raito_grant" "grant2" { +resource "raito_grant" "grant_purpose1" { name = "Grant2" description = "Grant with inherited who" + category = "purpose" state = "Active" who = [ { access_control = raito_grant.grant1.id } ] - data_source = raito_datasource.ds.id + data_source = [ + { + data_source : raito_datasource.ds.id + type : "role" + } + ] } \ No newline at end of file diff --git a/examples/resources/raito_grant_category/import.sh b/examples/resources/raito_grant_category/import.sh new file mode 100644 index 0000000..583dd4e --- /dev/null +++ b/examples/resources/raito_grant_category/import.sh @@ -0,0 +1,2 @@ +#Import grant. Not that who and what_data_objects will not be imported +terraform import raito_grant_category.example GrantCategoryId \ No newline at end of file diff --git a/examples/resources/raito_grant_category/resource.tf b/examples/resources/raito_grant_category/resource.tf new file mode 100644 index 0000000..04766ff --- /dev/null +++ b/examples/resources/raito_grant_category/resource.tf @@ -0,0 +1,28 @@ +resource "raito_datasource" "ds" { + name = "exampleDS" +} + +resource "raito_grant_category" "example_category" { + name = "exampleCategory" + description = "A simple category" + icon = "testIcon" + can_create = true + allow_duplicated_names = true + multi_data_source = true + default_type_per_data_source = [ + { + data_source : raito_datasource.ds.id + type : "table" + } + ] + allowed_who_items = { + user = true + group = true + inheritance = true + self = true + categories = ["otherCategoryId"] + } + allowed_what_items = { + data_object = true + } +} \ No newline at end of file diff --git a/examples/resources/raito_purpose/import.sh b/examples/resources/raito_purpose/import.sh deleted file mode 100644 index 0af2435..0000000 --- a/examples/resources/raito_purpose/import.sh +++ /dev/null @@ -1,2 +0,0 @@ -#Import purpose. Not that who and what will not be imported -terraform import raito_purpose.example PurposeId \ No newline at end of file diff --git a/examples/resources/raito_purpose/resource.tf b/examples/resources/raito_purpose/resource.tf deleted file mode 100644 index c7a7c01..0000000 --- a/examples/resources/raito_purpose/resource.tf +++ /dev/null @@ -1,25 +0,0 @@ -resource "raito_datasource" "ds" { - name = "exampleDS" -} - -resource "raito_grant" "grant1" { - name = "An existing grant" -} - -resource "raito_purpose" "example_purpose" { - name = "Example Purpose" - description = "This is an example purpose" - state = "Inactive" - what = [ - raito_grant.grant1.id - ] - who = [ - { - user = "user1@company.com" - }, - { - user = "user2@company.com", - promise_duration : 604800 - } - ] -} \ No newline at end of file diff --git a/go.mod b/go.mod index 0db7228..7161858 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/matoous/go-nanoid/v2 v2.1.0 github.com/raito-io/enumer v0.1.4 github.com/raito-io/golang-set v0.0.4 - github.com/raito-io/sdk-go v0.0.13-dev0 + github.com/raito-io/sdk-go v0.0.13 ) require ( @@ -31,19 +31,19 @@ require ( github.com/alexflint/go-scalar v1.2.0 // indirect github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect github.com/armon/go-radix v1.0.0 // indirect - github.com/aws/aws-sdk-go-v2 v1.32.5 // indirect - github.com/aws/aws-sdk-go-v2/config v1.28.5 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.17.46 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.20 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.24 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.24 // indirect + github.com/aws/aws-sdk-go-v2 v1.32.6 // indirect + github.com/aws/aws-sdk-go-v2/config v1.28.6 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.17.47 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.21 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.25 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.25 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect - github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.47.0 // indirect + github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.47.1 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.5 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.24.6 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.5 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.33.1 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.6 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.24.7 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.6 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.33.2 // indirect github.com/aws/smithy-go v1.22.1 // indirect github.com/bgentry/speakeasy v0.2.0 // indirect github.com/bmatcuk/doublestar/v4 v4.7.1 // indirect diff --git a/go.sum b/go.sum index f0756c9..400f622 100644 --- a/go.sum +++ b/go.sum @@ -34,32 +34,32 @@ github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/aws/aws-sdk-go-v2 v1.32.5 h1:U8vdWJuY7ruAkzaOdD7guwJjD06YSKmnKCJs7s3IkIo= -github.com/aws/aws-sdk-go-v2 v1.32.5/go.mod h1:P5WJBrYqqbWVaOxgH0X/FYYD47/nooaPOZPlQdmiN2U= -github.com/aws/aws-sdk-go-v2/config v1.28.5 h1:Za41twdCXbuyyWv9LndXxZZv3QhTG1DinqlFsSuvtI0= -github.com/aws/aws-sdk-go-v2/config v1.28.5/go.mod h1:4VsPbHP8JdcdUDmbTVgNL/8w9SqOkM5jyY8ljIxLO3o= -github.com/aws/aws-sdk-go-v2/credentials v1.17.46 h1:AU7RcriIo2lXjUfHFnFKYsLCwgbz1E7Mm95ieIRDNUg= -github.com/aws/aws-sdk-go-v2/credentials v1.17.46/go.mod h1:1FmYyLGL08KQXQ6mcTlifyFXfJVCNJTVGuQP4m0d/UA= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.20 h1:sDSXIrlsFSFJtWKLQS4PUWRvrT580rrnuLydJrCQ/yA= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.20/go.mod h1:WZ/c+w0ofps+/OUqMwWgnfrgzZH1DZO1RIkktICsqnY= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.24 h1:4usbeaes3yJnCFC7kfeyhkdkPtoRYPa/hTmCqMpKpLI= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.24/go.mod h1:5CI1JemjVwde8m2WG3cz23qHKPOxbpkq0HaoreEgLIY= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.24 h1:N1zsICrQglfzaBnrfM0Ys00860C+QFwu6u/5+LomP+o= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.24/go.mod h1:dCn9HbJ8+K31i8IQ8EWmWj0EiIk0+vKiHNMxTTYveAg= +github.com/aws/aws-sdk-go-v2 v1.32.6 h1:7BokKRgRPuGmKkFMhEg/jSul+tB9VvXhcViILtfG8b4= +github.com/aws/aws-sdk-go-v2 v1.32.6/go.mod h1:P5WJBrYqqbWVaOxgH0X/FYYD47/nooaPOZPlQdmiN2U= +github.com/aws/aws-sdk-go-v2/config v1.28.6 h1:D89IKtGrs/I3QXOLNTH93NJYtDhm8SYa9Q5CsPShmyo= +github.com/aws/aws-sdk-go-v2/config v1.28.6/go.mod h1:GDzxJ5wyyFSCoLkS+UhGB0dArhb9mI+Co4dHtoTxbko= +github.com/aws/aws-sdk-go-v2/credentials v1.17.47 h1:48bA+3/fCdi2yAwVt+3COvmatZ6jUDNkDTIsqDiMUdw= +github.com/aws/aws-sdk-go-v2/credentials v1.17.47/go.mod h1:+KdckOejLW3Ks3b0E3b5rHsr2f9yuORBum0WPnE5o5w= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.21 h1:AmoU1pziydclFT/xRV+xXE/Vb8fttJCLRPv8oAkprc0= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.21/go.mod h1:AjUdLYe4Tgs6kpH4Bv7uMZo7pottoyHMn4eTcIcneaY= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.25 h1:s/fF4+yDQDoElYhfIVvSNyeCydfbuTKzhxSXDXCPasU= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.25/go.mod h1:IgPfDv5jqFIzQSNbUEMoitNooSMXjRSDkhXv8jiROvU= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.25 h1:ZntTCl5EsYnhN/IygQEUugpdwbhdkom9uHcbCftiGgA= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.25/go.mod h1:DBdPrgeocww+CSl1C8cEV8PN1mHMBhuCDLpXezyvWkE= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= -github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.47.0 h1:9WEhV3JmFhSMnKaY2SqcPb0bM5XIoMmAy62Fj5TNMwk= -github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.47.0/go.mod h1:TxsMf+uRm3AHGUs2BSmnxz99BqUd6f9EiuDEhRppTY8= +github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.47.1 h1:isjmZUmhAMzCLs38LnWVIKqWRSkItqZVGpdJowlmV/Y= +github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.47.1/go.mod h1:U+GnB0KkXI5SgVMzW2J1FHMGbAiObr1XaIGZSMejLlI= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 h1:iXtILhvDxB6kPvEXgsDhGaZCSC6LQET5ZHSdJozeI0Y= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1/go.mod h1:9nu0fVANtYiAePIBh2/pFUSwtJ402hLnp854CNoDOeE= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.5 h1:wtpJ4zcwrSbwhECWQoI/g6WM9zqCcSpHDJIWSbMLOu4= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.5/go.mod h1:qu/W9HXQbbQ4+1+JcZp0ZNPV31ym537ZJN+fiS7Ti8E= -github.com/aws/aws-sdk-go-v2/service/sso v1.24.6 h1:3zu537oLmsPfDMyjnUS2g+F2vITgy5pB74tHI+JBNoM= -github.com/aws/aws-sdk-go-v2/service/sso v1.24.6/go.mod h1:WJSZH2ZvepM6t6jwu4w/Z45Eoi75lPN7DcydSRtJg6Y= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.5 h1:K0OQAsDywb0ltlFrZm0JHPY3yZp/S9OaoLU33S7vPS8= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.5/go.mod h1:ORITg+fyuMoeiQFiVGoqB3OydVTLkClw/ljbblMq6Cc= -github.com/aws/aws-sdk-go-v2/service/sts v1.33.1 h1:6SZUVRQNvExYlMLbHdlKB48x0fLbc2iVROyaNEwBHbU= -github.com/aws/aws-sdk-go-v2/service/sts v1.33.1/go.mod h1:GqWyYCwLXnlUB1lOAXQyNSPqPLQJvmo8J0DWBzp9mtg= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.6 h1:50+XsN70RS7dwJ2CkVNXzj7U2L1HKP8nqTd3XWEXBN4= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.6/go.mod h1:WqgLmwY7so32kG01zD8CPTJWVWM+TzJoOVHwTg4aPug= +github.com/aws/aws-sdk-go-v2/service/sso v1.24.7 h1:rLnYAfXQ3YAccocshIH5mzNNwZBkBo+bP6EhIxak6Hw= +github.com/aws/aws-sdk-go-v2/service/sso v1.24.7/go.mod h1:ZHtuQJ6t9A/+YDuxOLnbryAmITtr8UysSny3qcyvJTc= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.6 h1:JnhTZR3PiYDNKlXy50/pNeix9aGMo6lLpXwJ1mw8MD4= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.6/go.mod h1:URronUEGfXZN1VpdktPSD1EkAL9mfrV+2F4sjH38qOY= +github.com/aws/aws-sdk-go-v2/service/sts v1.33.2 h1:s4074ZO1Hk8qv65GqNXqDjmkf4HSQqJukaLuuW0TpDA= +github.com/aws/aws-sdk-go-v2/service/sts v1.33.2/go.mod h1:mVggCnIWoM09jP71Wh+ea7+5gAp53q+49wDFs1SW5z8= github.com/aws/smithy-go v1.22.1 h1:/HPHZQ0g7f4eUeK6HKglFz8uwVfZKgoI25rb/J+dnro= github.com/aws/smithy-go v1.22.1/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= github.com/bgentry/speakeasy v0.2.0 h1:tgObeVOf8WAvtuAX6DhJ4xks4CFNwPDZiqzGqIHE51E= @@ -226,8 +226,8 @@ github.com/raito-io/enumer v0.1.4 h1:r2QqGMjfKwn+yMHo4ybOAWvYON4pLBy+ucVP5niyHK4 github.com/raito-io/enumer v0.1.4/go.mod h1:+tSaVlYRuVnf2vA7ETf8t7/Mzq/sgvWT/dHeMVOjBu8= github.com/raito-io/golang-set v0.0.4 h1:7zk8r1TCE/F9JOOgseIXYx7oZJdC9/j5uivkCYjnCg0= github.com/raito-io/golang-set v0.0.4/go.mod h1:ktKACNnQeSpzo0Nes6jDTs74UOau8psJpAesatiEKQE= -github.com/raito-io/sdk-go v0.0.13-dev0 h1:kdjyMSzMW5bd8OkbUF6BOJbzlI1R8gz8iz9Y0GXZqKU= -github.com/raito-io/sdk-go v0.0.13-dev0/go.mod h1:w09xEXbcxbtMCY4jGWwPsP7TLLlYM5HKHh8M/T7UlH8= +github.com/raito-io/sdk-go v0.0.13 h1:Nujz7TX+Ncf27mw54OAR01ymfcHR5NLghbgVT3LupUg= +github.com/raito-io/sdk-go v0.0.13/go.mod h1:mBfHUWMZ311lQiKfdc5Lrxxu06GTmOn7Gfu8K3Rc4gQ= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= diff --git a/internal/grant_category_resource.go b/internal/grant_category_resource.go new file mode 100644 index 0000000..2e7349c --- /dev/null +++ b/internal/grant_category_resource.go @@ -0,0 +1,558 @@ +package internal + +import ( + "context" + "errors" + "fmt" + + "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" + "github.com/hashicorp/terraform-plugin-framework/attr" + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/objectdefault" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/setdefault" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/raito-io/sdk-go" + raitoType "github.com/raito-io/sdk-go/types" +) + +var _ resource.Resource = (*GrantCategoryResource)(nil) + +type GrantCategoryResourceModel struct { + Id types.String `tfsdk:"id"` + Name types.String `tfsdk:"name"` + Description types.String `tfsdk:"description"` + Icon types.String `tfsdk:"icon"` + IsSystem types.Bool `tfsdk:"is_system"` + IsDefault types.Bool `tfsdk:"is_default"` + CanCreate types.Bool `tfsdk:"can_create"` + AllowDuplicateNames types.Bool `tfsdk:"allow_duplicate_names"` + MultiDataSource types.Bool `tfsdk:"multi_data_source"` + DefaultTypePerDataSource types.Set `tfsdk:"default_type_per_data_source"` + AllowedWhoItems types.Object `tfsdk:"allowed_who_items"` + AllowedWhatItems types.Object `tfsdk:"allowed_what_items"` +} + +func (m *GrantCategoryResourceModel) ToGrantCategoryInput() raitoType.GrantCategoryInput { + defaultTypePerDataSourceValues := m.DefaultTypePerDataSource.Elements() + defaultTypePerDS := make([]raitoType.GrantCategoryTypeForDataSourceInput, 0, len(defaultTypePerDataSourceValues)) + + for _, v := range defaultTypePerDataSourceValues { + vObject := v.(types.Object) + attributes := vObject.Attributes() + + typeForDataSource := raitoType.GrantCategoryTypeForDataSourceInput{ + DataSource: attributes["data_source"].(types.String).ValueString(), + Type: attributes["type"].(types.String).ValueString(), + } + + defaultTypePerDS = append(defaultTypePerDS, typeForDataSource) + } + + allowedWhoCategoriesValues := m.AllowedWhoItems.Attributes()["categories"].(types.Set).Elements() + allowedWhoCategories := make([]string, 0, len(allowedWhoCategoriesValues)) + + for _, v := range allowedWhoCategoriesValues { + allowedWhoCategories = append(allowedWhoCategories, v.(types.String).ValueString()) + } + + input := raitoType.GrantCategoryInput{ + Name: m.Name.ValueStringPointer(), + Description: m.Description.ValueStringPointer(), + Icon: m.Icon.ValueStringPointer(), + CanCreate: m.CanCreate.ValueBoolPointer(), + AllowDuplicateNames: m.AllowDuplicateNames.ValueBoolPointer(), + MultiDataSource: m.MultiDataSource.ValueBoolPointer(), + DefaultTypePerDataSource: defaultTypePerDS, + AllowedWhoItems: &raitoType.GrantCategoryAllowedWhoItemsInput{ + User: m.AllowedWhoItems.Attributes()["user"].(types.Bool).ValueBool(), + Group: m.AllowedWhoItems.Attributes()["group"].(types.Bool).ValueBool(), + Inheritance: m.AllowedWhoItems.Attributes()["inheritance"].(types.Bool).ValueBool(), + Self: m.AllowedWhoItems.Attributes()["self"].(types.Bool).ValueBool(), + Categories: allowedWhoCategories, + }, + AllowedWhatItems: &raitoType.GrantCategoryAllowedWhatItemsInput{ + DataObject: m.AllowedWhatItems.Attributes()["data_object"].(types.Bool).ValueBool(), + }, + } + + return input +} + +type GrantCategoryResource struct { + client *sdk.RaitoClient +} + +func NewGrantCategoryResource() resource.Resource { + return &GrantCategoryResource{} +} + +func (g *GrantCategoryResource) Metadata(ctx context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) { + response.TypeName = request.ProviderTypeName + "_grant_category" +} + +func (g *GrantCategoryResource) Schema(ctx context.Context, request resource.SchemaRequest, response *resource.SchemaResponse) { + response.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ + Required: false, + Optional: false, + Computed: true, + Sensitive: false, + Description: "The ID of the grant category", + MarkdownDescription: "The ID of the grant category", + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + }, + "name": schema.StringAttribute{ + Required: true, + Optional: false, + Computed: false, + Sensitive: false, + Description: "The name of the grant category", + MarkdownDescription: "The name of the grant category", + Validators: []validator.String{stringvalidator.LengthAtLeast(3)}, + }, + "description": schema.StringAttribute{ + Required: false, + Optional: true, + Computed: true, + Sensitive: false, + Description: "The description of the grant category", + MarkdownDescription: "The description of the grant category", + Default: stringdefault.StaticString(""), + }, + "icon": schema.StringAttribute{ + Required: true, + Optional: false, + Computed: false, + Sensitive: false, + Description: "The icon of the grant category", + MarkdownDescription: "The icon of the grant category", + }, + "is_system": schema.BoolAttribute{ + Required: false, + Optional: false, + Computed: true, + Sensitive: false, + Description: "Whether the grant category is a system category", + MarkdownDescription: "Whether the grant category is a system category", + }, + "is_default": schema.BoolAttribute{ + Required: false, + Optional: false, + Computed: true, + Sensitive: false, + Description: "Whether the grant category is a default category", + MarkdownDescription: "Whether the grant category is a default category", + }, + "can_create": schema.BoolAttribute{ + Required: false, + Optional: true, + Computed: true, + Sensitive: false, + Description: "Whether the user can create grants in this category", + MarkdownDescription: "Whether the user can create grants in this category", + Default: booldefault.StaticBool(true), + }, + "allow_duplicate_names": schema.BoolAttribute{ + Required: false, + Optional: true, + Computed: true, + Sensitive: false, + Description: "Whether the user can create grants with duplicate names in this category", + MarkdownDescription: "Whether the user can create grants with duplicate names in this category", + Default: booldefault.StaticBool(true), + }, + "multi_data_source": schema.BoolAttribute{ + Required: false, + Optional: true, + Computed: true, + Sensitive: false, + Description: "Whether the grant category supports multiple data sources", + MarkdownDescription: "Whether the grant category supports multiple data sources", + Default: booldefault.StaticBool(true), + }, + "default_type_per_data_source": schema.SetNestedAttribute{ + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "data_source": schema.StringAttribute{ + Required: true, + Optional: false, + Computed: false, + Sensitive: false, + Description: "The data source for which the default type is set", + MarkdownDescription: "The data source for which the default type is set", + }, + "type": schema.StringAttribute{ + Required: true, + Optional: false, + Computed: false, + Sensitive: false, + Description: "The default type for the data source", + MarkdownDescription: "The default type for the data source", + }, + }, + }, + Required: false, + Optional: true, + Computed: true, + Sensitive: false, + Description: "The default category for each data source, type pair", + MarkdownDescription: "The default category for each data source, type pair", + Default: setdefault.StaticValue(types.SetValueMust(types.ObjectType{AttrTypes: map[string]attr.Type{"data_source": types.StringType, "type": types.StringType}}, []attr.Value{})), + }, + "allowed_who_items": schema.SingleNestedAttribute{ + Attributes: map[string]schema.Attribute{ + "user": schema.BoolAttribute{ + Required: false, + Optional: true, + Computed: true, + Sensitive: false, + Description: "Whether the user is allowed as WHO item for the grants of this category", + MarkdownDescription: "Whether the user is allowed as WHO item for the grants of this category", + Default: booldefault.StaticBool(true), + }, + "group": schema.BoolAttribute{ + Required: false, + Optional: true, + Computed: true, + Sensitive: false, + Description: "Whether the group is allowed as WHO item for the grants of this category", + MarkdownDescription: "Whether the group is allowed as WHO item for the grants of this category", + Default: booldefault.StaticBool(true), + }, + "inheritance": schema.BoolAttribute{ + Required: false, + Optional: true, + Computed: true, + Sensitive: false, + Description: "Whether the inheritance is allowed as WHO item for the grants of this category", + MarkdownDescription: "Whether the inheritance is allowed as WHO item for the grants of this category", + Default: booldefault.StaticBool(true), + }, + "self": schema.BoolAttribute{ + Required: false, + Optional: true, + Computed: true, + Sensitive: false, + Description: "Whether the self is allowed as WHO item for the grants of this category", + MarkdownDescription: "Whether the self is allowed as WHO item for the grants of this category", + Default: booldefault.StaticBool(true), + }, + "categories": schema.SetAttribute{ + ElementType: types.StringType, + Required: false, + Optional: true, + Computed: true, + Sensitive: false, + Description: "The allowed WHO items for the grants of this category", + MarkdownDescription: "The allowed WHO items for the grants of this category", + Default: setdefault.StaticValue(types.SetValueMust(types.StringType, []attr.Value{})), + }, + }, + Required: false, + Optional: true, + Computed: true, + Sensitive: false, + Description: "The allowed WHO items for the grants of this category", + MarkdownDescription: "The allowed WHO items for the grants of this category", + Default: objectdefault.StaticValue(types.ObjectValueMust(map[string]attr.Type{ + "user": types.BoolType, + "group": types.BoolType, + "inheritance": types.BoolType, + "self": types.BoolType, + "categories": types.SetType{ElemType: types.StringType}, + }, map[string]attr.Value{ + "user": types.BoolValue(true), + "group": types.BoolValue(true), + "inheritance": types.BoolValue(true), + "self": types.BoolValue(true), + "categories": types.SetValueMust(types.StringType, []attr.Value{}), + })), + }, + "allowed_what_items": schema.SingleNestedAttribute{ + Attributes: map[string]schema.Attribute{ + "data_object": schema.BoolAttribute{ + Required: false, + Optional: true, + Computed: true, + Sensitive: false, + Description: "The allowed WHAT items for the grants of this category", + MarkdownDescription: "The allowed WHAT items for the grants of this category", + Default: booldefault.StaticBool(true), + }, + }, + Required: false, + Optional: true, + Computed: true, + Sensitive: false, + Description: "The allowed WHAT items for the grants of this category", + MarkdownDescription: "The allowed WHAT items for the grants of this category", + Default: objectdefault.StaticValue(types.ObjectValueMust(map[string]attr.Type{ + "data_object": types.BoolType, + }, + map[string]attr.Value{ + "data_object": types.BoolValue(true), + }, + )), + }, + }, + Description: "The grant category resource allows you to manage grant categories in Raito.", + MarkdownDescription: "The grant category resource allows you to manage grant categories in Raito.", + Version: 1, + } +} + +func (g *GrantCategoryResource) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) { + var data GrantCategoryResourceModel + + // Read terraform plan data into the model + response.Diagnostics.Append(request.Plan.Get(ctx, &data)...) + + if response.Diagnostics.HasError() { + return + } + + grantCategoryResult, err := g.client.GrantCategory().CreateGrantCategory(ctx, data.ToGrantCategoryInput()) + if err != nil { + response.Diagnostics.AddError("Failed to create grant category", err.Error()) + + return + } + + data.Id = types.StringValue(grantCategoryResult.Id) + response.Diagnostics.Append(response.State.Set(ctx, data)...) + + response.Diagnostics.Append(setGrantCategoryResourceData(grantCategoryResult, &data)...) + + if response.Diagnostics.HasError() { + return + } + + response.Diagnostics.Append(response.State.Set(ctx, data)...) +} + +func (g *GrantCategoryResource) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) { + var stateData GrantCategoryResourceModel + + // Read terraform plan stateData into model + response.Diagnostics.Append(request.State.Get(ctx, &stateData)...) + + if response.Diagnostics.HasError() { + return + } + + category, err := g.client.GrantCategory().GetGrantCategory(ctx, stateData.Id.ValueString()) + if err != nil { + var notFoundErr *raitoType.ErrNotFound + if !errors.As(err, ¬FoundErr) { + response.State.RemoveResource(ctx) + } else { + response.Diagnostics.AddError("Failed to get grant category", err.Error()) + } + + return + } + + response.Diagnostics.Append(setGrantCategoryResourceData(category, &stateData)...) + + if response.Diagnostics.HasError() { + return + } + + response.Diagnostics.Append(response.State.Set(ctx, stateData)...) +} + +func (g *GrantCategoryResource) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) { + var data GrantCategoryResourceModel + + // Read terraform plan data into the model + response.Diagnostics.Append(request.Plan.Get(ctx, &data)...) + + if response.Diagnostics.HasError() { + return + } + + // Update grant category + gc, err := g.client.GrantCategory().UpdateGrantCategory(ctx, data.Id.ValueString(), data.ToGrantCategoryInput()) + if err != nil { + response.Diagnostics.AddError("Failed to update grant category", err.Error()) + + return + } + + response.Diagnostics.Append(setGrantCategoryResourceData(gc, &data)...) + + if response.Diagnostics.HasError() { + return + } + + response.Diagnostics.Append(response.State.Set(ctx, data)...) +} + +func (g *GrantCategoryResource) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) { + var data GrantCategoryResourceModel + + // Read terraform plan stateData into model + response.Diagnostics.Append(request.State.Get(ctx, &data)...) + + if response.Diagnostics.HasError() { + return + } + + err := g.client.GrantCategory().DeleteGrantCategory(ctx, data.Id.ValueString()) + if err != nil { + response.Diagnostics.AddError("Failed to delete grant category", err.Error()) + + return + } + + response.State.RemoveResource(ctx) +} + +func (g *GrantCategoryResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { + if req.ProviderData == nil { + return + } + + client, ok := req.ProviderData.(*sdk.RaitoClient) + if !ok { + resp.Diagnostics.AddError( + "Unexpected Resource Configure Type", + fmt.Sprintf("Expected *sdk.RaitoClient, got: %T. Please report this issue to the provider developers.", req.ProviderData), + ) + + return + } + + if client == nil { + resp.Diagnostics.AddError( + "Unexpected Resource Configure Type", + "Expected *sdk.RaitoClient, not to be nil.", + ) + + return + } + + g.client = client +} +func (g *GrantCategoryResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) +} + +func setGrantCategoryResourceData(data *raitoType.GrantCategoryDetails, resp *GrantCategoryResourceModel) (diags diag.Diagnostics) { + resp.Id = types.StringValue(data.Id) + resp.Name = types.StringValue(data.Name) + resp.Description = types.StringValue(data.Description) + resp.Icon = types.StringValue(data.Icon) + resp.IsSystem = types.BoolValue(data.IsSystem) + resp.IsDefault = types.BoolValue(data.IsDefault) + resp.CanCreate = types.BoolValue(data.CanCreate) + resp.AllowDuplicateNames = types.BoolValue(data.AllowDuplicateNames) + resp.MultiDataSource = types.BoolValue(data.MultiDataSource) + + // Default types per DS + defaultTypesPerDs := make([]attr.Value, 0, len(data.DefaultTypePerDataSource)) + + for _, v := range data.DefaultTypePerDataSource { + objectValue, diag := types.ObjectValue(map[string]attr.Type{ + "data_source": types.StringType, + "type": types.StringType, + }, + map[string]attr.Value{ + "data_source": types.StringValue(v.GetDataSource()), + "type": types.StringValue(v.GetType()), + }) + + diags.Append(diag...) + + if diags.HasError() { + return diags + } + + defaultTypesPerDs = append(defaultTypesPerDs, objectValue) + } + + defaultTypesPerDsAttr, diag := types.SetValue(types.ObjectType{ + AttrTypes: map[string]attr.Type{ + "data_source": types.StringType, + "type": types.StringType, + }, + }, defaultTypesPerDs) + + diags.Append(diag...) + + if diags.HasError() { + return diags + } + + resp.DefaultTypePerDataSource = defaultTypesPerDsAttr + + // Allowed WHO items + whoCategoryValues := make([]attr.Value, 0, len(data.AllowedWhoItems.Categories)) + for _, v := range data.AllowedWhoItems.Categories { + whoCategoryValues = append(whoCategoryValues, types.StringValue(v)) + } + + whoCategories, diag := types.SetValue(types.StringType, whoCategoryValues) + + diags.Append(diag...) + + if diags.HasError() { + return diags + } + + allowedWhoItems, diag := types.ObjectValue( + map[string]attr.Type{ + "user": types.BoolType, + "group": types.BoolType, + "inheritance": types.BoolType, + "self": types.BoolType, + "categories": types.SetType{ElemType: types.StringType}, + }, + map[string]attr.Value{ + "user": types.BoolValue(data.AllowedWhoItems.User), + "group": types.BoolValue(data.AllowedWhoItems.Group), + "inheritance": types.BoolValue(data.AllowedWhoItems.Inheritance), + "self": types.BoolValue(data.AllowedWhoItems.Self), + "categories": whoCategories, + }, + ) + + diags.Append(diag...) + + if diags.HasError() { + return diags + } + + resp.AllowedWhoItems = allowedWhoItems + + // Allowed WHAT items + allowedWhatItems, diag := types.ObjectValue( + map[string]attr.Type{ + "data_object": types.BoolType, + }, + map[string]attr.Value{ + "data_object": types.BoolValue(data.AllowedWhatItems.DataObject), + }, + ) + + diags.Append(diag...) + + if diags.HasError() { + return diags + } + + resp.AllowedWhatItems = allowedWhatItems + + return diags +} diff --git a/internal/grant_category_resource_test.go b/internal/grant_category_resource_test.go new file mode 100644 index 0000000..b1c6cf6 --- /dev/null +++ b/internal/grant_category_resource_test.go @@ -0,0 +1,90 @@ +package internal + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/tfversion" + gonanoid "github.com/matoous/go-nanoid/v2" +) + +func TestAccGrantCategoryResource(t *testing.T) { + testId := gonanoid.Must(8) + + t.Run("basic", func(t *testing.T) { + resource.Test(t, resource.TestCase{ + IsUnitTest: false, + PreCheck: func() { + AccProviderPreCheck(t) + }, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_0_0), + }, + Steps: []resource.TestStep{ + { + Config: providerConfig + fmt.Sprintf(` +resource "raito_grant_category" "test" { + name = "tfTestGrantCategory-%s" + description = "test description" + icon = "test" +} +`, testId), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("raito_grant_category.test", "name", "tfTestGrantCategory-"+testId), + resource.TestCheckResourceAttr("raito_grant_category.test", "description", "test description"), + resource.TestCheckResourceAttr("raito_grant_category.test", "is_system", "false"), + resource.TestCheckResourceAttr("raito_grant_category.test", "is_default", "false"), + resource.TestCheckResourceAttr("raito_grant_category.test", "can_create", "true"), + resource.TestCheckResourceAttr("raito_grant_category.test", "allow_duplicate_names", "true"), + resource.TestCheckResourceAttr("raito_grant_category.test", "multi_data_source", "true"), + resource.TestCheckResourceAttr("raito_grant_category.test", "default_type_per_data_source.#", "0"), + resource.TestCheckResourceAttr("raito_grant_category.test", "allowed_who_items.user", "true"), + resource.TestCheckResourceAttr("raito_grant_category.test", "allowed_who_items.group", "true"), + resource.TestCheckResourceAttr("raito_grant_category.test", "allowed_who_items.inheritance", "true"), + resource.TestCheckResourceAttr("raito_grant_category.test", "allowed_who_items.self", "true"), + resource.TestCheckResourceAttr("raito_grant_category.test", "allowed_who_items.categories.#", "0"), + resource.TestCheckResourceAttr("raito_grant_category.test", "allowed_what_items.data_object", "true"), + ), + }, + { + ResourceName: "raito_grant_category.test", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: providerConfig + fmt.Sprintf(` +resource "raito_grant_category" "test" { + name = "tfTestGrantCategory-%s" + description = "test description update" + icon = "test" + allow_duplicate_names = false + multi_data_source = false + allowed_who_items = { + user = false + } +} +`, testId), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("raito_grant_category.test", "name", "tfTestGrantCategory-"+testId), + resource.TestCheckResourceAttr("raito_grant_category.test", "description", "test description update"), + resource.TestCheckResourceAttr("raito_grant_category.test", "is_system", "false"), + resource.TestCheckResourceAttr("raito_grant_category.test", "is_default", "false"), + resource.TestCheckResourceAttr("raito_grant_category.test", "can_create", "true"), + resource.TestCheckResourceAttr("raito_grant_category.test", "allow_duplicate_names", "false"), + resource.TestCheckResourceAttr("raito_grant_category.test", "multi_data_source", "false"), + resource.TestCheckResourceAttr("raito_grant_category.test", "default_type_per_data_source.#", "0"), + resource.TestCheckResourceAttr("raito_grant_category.test", "allowed_who_items.user", "false"), + resource.TestCheckResourceAttr("raito_grant_category.test", "allowed_who_items.group", "true"), + resource.TestCheckResourceAttr("raito_grant_category.test", "allowed_who_items.inheritance", "true"), + resource.TestCheckResourceAttr("raito_grant_category.test", "allowed_who_items.self", "true"), + resource.TestCheckResourceAttr("raito_grant_category.test", "allowed_who_items.categories.#", "0"), + resource.TestCheckResourceAttr("raito_grant_category.test", "allowed_what_items.data_object", "true"), + ), + }, + // Resource is automatically deleted + }, + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + }) + }) +} diff --git a/internal/grant_resource.go b/internal/grant_resource.go index 472e03a..73f18d6 100644 --- a/internal/grant_resource.go +++ b/internal/grant_resource.go @@ -42,8 +42,8 @@ type GrantResourceModel struct { InheritanceLocked types.Bool `tfsdk:"inheritance_locked"` // GrantResourceModel properties. - Type types.String `tfsdk:"type"` - DataSource types.String `tfsdk:"data_source"` + Category types.String `tfsdk:"category"` + DataSource types.Set `tfsdk:"data_source"` WhatDataObjects types.Set `tfsdk:"what_data_objects"` WhatAbacRule types.Object `tfsdk:"what_abac_rule"` WhatLocked types.Bool `tfsdk:"what_locked"` @@ -83,16 +83,23 @@ func (m *GrantResourceModel) ToAccessProviderInput(ctx context.Context, client * } if !m.DataSource.IsNull() && !m.DataSource.IsUnknown() { - var apType *string - if !m.Type.IsUnknown() { - apType = m.Type.ValueStringPointer() - } + dataSourceElements := m.DataSource.Elements() + + result.DataSources = make([]raitoType.AccessProviderDataSourceInput, 0, len(dataSourceElements)) + + for _, dsElement := range dataSourceElements { + dsAttributes := dsElement.(types.Object).Attributes() + + var apType *string - result.DataSources = []raitoType.AccessProviderDataSourceInput{ - { - DataSource: m.DataSource.ValueString(), + if !dsAttributes["type"].(types.String).IsUnknown() { + apType = dsAttributes["type"].(types.String).ValueStringPointer() + } + + result.DataSources = append(result.DataSources, raitoType.AccessProviderDataSourceInput{ + DataSource: dsAttributes["data_source"].(types.String).ValueString(), Type: apType, - }, + }) } } @@ -118,6 +125,10 @@ func (m *GrantResourceModel) ToAccessProviderInput(ctx context.Context, client * }) } + if !m.Category.IsUnknown() { + result.Category = m.Category.ValueStringPointer() + } + return diagnostics } @@ -131,6 +142,7 @@ func (m *GrantResourceModel) whatDoToApInput(result *raitoType.AccessProviderInp whatDataObjectAttributes := whatDataObjectObject.Attributes() fullname := whatDataObjectAttributes["fullname"].(types.String).ValueString() + dataSource := whatDataObjectAttributes["data_source"].(types.String).ValueString() permissionSet := whatDataObjectAttributes["permissions"].(types.Set) permissions := make([]*string, 0, len(permissionSet.Elements())) @@ -148,9 +160,6 @@ func (m *GrantResourceModel) whatDoToApInput(result *raitoType.AccessProviderInp globalPermissions = append(globalPermissions, permission.ValueStringPointer()) } - // Assume that currently only 1 dataSource is provided - dataSource := result.DataSources[0].DataSource - result.WhatDataObjects = append(result.WhatDataObjects, raitoType.AccessProviderWhatInputDO{ DataObjectByName: []raitoType.AccessProviderWhatDoByNameInput{{ Fullname: fullname, @@ -173,18 +182,45 @@ func (m *GrantResourceModel) FromAccessProvider(ctx context.Context, client *sdk m.SetAccessProviderResourceModel(apResourceModel) - if len(ap.SyncData) != 1 { - diagnostics.AddError("Failed to get data source", fmt.Sprintf("Expected exactly one data source, got: %d.", len(ap.SyncData))) + dataSourceValues := make([]attr.Value, 0, len(ap.SyncData)) - return diagnostics + for _, ds := range ap.SyncData { + dsId := types.StringValue(ds.DataSource.Id) + dsType := types.StringPointerValue(ds.AccessProviderType.Type) + + dataSource, diag := types.ObjectValue(map[string]attr.Type{ + "data_source": types.StringType, + "type": types.StringType, + }, + map[string]attr.Value{ + "data_source": dsId, + "type": dsType, + }) + + diagnostics.Append(diag...) + + if diagnostics.HasError() { + return diagnostics + } + + dataSourceValues = append(dataSourceValues, dataSource) } - m.DataSource = types.StringValue(ap.SyncData[0].DataSource.Id) + dataSources, diag := types.SetValue(types.ObjectType{ + AttrTypes: map[string]attr.Type{ + "data_source": types.StringType, + "type": types.StringType, + }, + }, dataSourceValues) + + diagnostics.Append(diag...) - if ap.SyncData[0].AccessProviderType != nil { - m.Type = types.StringPointerValue(ap.SyncData[0].AccessProviderType.Type) + if diagnostics.HasError() { + return diagnostics } + m.DataSource = dataSources + m.WhatLocked = types.BoolValue(slices.ContainsFunc(ap.Locks, func(l raitoType.AccessProviderLocksAccessProviderLockData) bool { return l.LockKey == raitoType.AccessProviderLockWhatlock })) @@ -200,6 +236,8 @@ func (m *GrantResourceModel) FromAccessProvider(ctx context.Context, client *sdk m.WhatAbacRule = object } + m.Category = types.StringValue(ap.Category.Id) + return diagnostics } @@ -379,27 +417,52 @@ func (g *GrantResource) Metadata(_ context.Context, request resource.MetadataReq func (g *GrantResource) Schema(_ context.Context, _ resource.SchemaRequest, response *resource.SchemaResponse) { attributes := g.schema("grant") - attributes["type"] = schema.StringAttribute{ + attributes["category"] = schema.StringAttribute{ Required: false, Optional: true, - Computed: false, + Computed: true, Sensitive: false, - Description: "The type of the grant", - MarkdownDescription: "The type of the grant", + Description: "The ID of the category of the grant", + MarkdownDescription: "The ID of the category of the grant", PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), stringplanmodifier.RequiresReplace(), }, } - attributes["data_source"] = schema.StringAttribute{ + attributes["data_source"] = schema.SetNestedAttribute{ + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "data_source": schema.StringAttribute{ + Required: true, + Optional: false, + Computed: false, + Sensitive: false, + Description: "The ID of the data source of the grant", + MarkdownDescription: "The ID of the data source of the grant", + Validators: []validator.String{ + stringvalidator.LengthAtLeast(3), + }, + }, + "type": schema.StringAttribute{ + Required: false, + Optional: true, + Computed: true, + Sensitive: false, + Description: "The implementation type of the grant for this data source", + MarkdownDescription: "The implementation type of the grant for this data source", + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + }, + }, + }, Required: true, Optional: false, Computed: false, Sensitive: false, Description: "The ID of the data source of the grant", MarkdownDescription: "The ID of the data source of the grant", - Validators: []validator.String{ - stringvalidator.LengthAtLeast(3), - }, + Validators: []validator.Set{setvalidator.SizeAtLeast(1)}, } attributes["what_data_objects"] = schema.SetNestedAttribute{ NestedObject: schema.NestedAttributeObject{ @@ -412,6 +475,14 @@ func (g *GrantResource) Schema(_ context.Context, _ resource.SchemaRequest, resp Description: "The full name of the data object in the data source", MarkdownDescription: "The full name of the data object in the data source", }, + "data_source": schema.StringAttribute{ + Required: true, + Optional: false, + Computed: false, + Sensitive: false, + Description: "The data source of the data object", + MarkdownDescription: "The data source of the data object", + }, "permissions": schema.SetAttribute{ ElementType: types.StringType, Required: false, @@ -452,9 +523,9 @@ func (g *GrantResource) Schema(_ context.Context, _ resource.SchemaRequest, resp Attributes: map[string]schema.Attribute{ "scope": schema.SetAttribute{ ElementType: types.StringType, - Required: false, - Optional: true, - Computed: true, + Required: true, + Optional: false, + Computed: false, Sensitive: false, Description: "Scope of the defined abac rule", MarkdownDescription: "Scope of the defined abac rule", @@ -552,9 +623,11 @@ func readGrantWhatItems(ctx context.Context, client *sdk.RaitoClient, data *Gran what := whatItem.GetItem() var id *string + var dataSourceId *string if what.DataObject != nil { id = &what.DataObject.FullName + dataSourceId = &what.DataObject.DataSource.Id } else { diagnostics.AddError("Invalid what data object", "Received data object is nil") @@ -572,7 +645,8 @@ func readGrantWhatItems(ctx context.Context, client *sdk.RaitoClient, data *Gran } stateWhatItems = append(stateWhatItems, types.ObjectValueMust(map[string]attr.Type{ - "fullname": types.StringType, + "fullname": types.StringType, + "data_source": types.StringType, "permissions": types.SetType{ ElemType: types.StringType, }, @@ -581,6 +655,7 @@ func readGrantWhatItems(ctx context.Context, client *sdk.RaitoClient, data *Gran }, }, map[string]attr.Value{ "fullname": types.StringPointerValue(id), + "data_source": types.StringPointerValue(dataSourceId), "permissions": types.SetValueMust(types.StringType, permissions), "global_permissions": types.SetValueMust(types.StringType, globalPermissions), })) @@ -588,7 +663,8 @@ func readGrantWhatItems(ctx context.Context, client *sdk.RaitoClient, data *Gran whatDataObject, whatDiag := types.SetValue(types.ObjectType{ AttrTypes: map[string]attr.Type{ - "fullname": types.StringType, + "fullname": types.StringType, + "data_source": types.StringType, "permissions": types.SetType{ ElemType: types.StringType, }, diff --git a/internal/grant_resource_test.go b/internal/grant_resource_test.go index d355a71..11d8520 100644 --- a/internal/grant_resource_test.go +++ b/internal/grant_resource_test.go @@ -29,10 +29,16 @@ data "raito_datasource" "ds" { resource "raito_grant" "test" { name = "tfTestGrant" description = "test description" - data_source = data.raito_datasource.ds.id + data_source = [ + { + data_source = data.raito_datasource.ds.id + type = "role" + } + ] what_data_objects = [ { - "fullname": "MASTER_DATA.SALES" + fullname = "MASTER_DATA.SALES" + data_source = data.raito_datasource.ds.id } ] who = [ @@ -45,7 +51,7 @@ resource "raito_grant" "test" { Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("raito_grant.test", "name", "tfTestGrant"), resource.TestCheckResourceAttr("raito_grant.test", "description", "test description"), - resource.TestCheckResourceAttrPair("raito_grant.test", "data_source", "data.raito_datasource.ds", "id"), + resource.TestCheckResourceAttrPair("raito_grant.test", "data_source.0.data_source", "data.raito_datasource.ds", "id"), resource.TestCheckResourceAttr("raito_grant.test", "what_data_objects.#", "1"), resource.TestCheckResourceAttr("raito_grant.test", "what_data_objects.0.fullname", "MASTER_DATA.SALES"), resource.TestCheckResourceAttr("raito_grant.test", "who.#", "1"), @@ -53,6 +59,7 @@ resource "raito_grant" "test" { resource.TestCheckResourceAttr("raito_grant.test", "who_locked", "true"), resource.TestCheckResourceAttr("raito_grant.test", "inheritance_locked", "false"), resource.TestCheckResourceAttr("raito_grant.test", "what_locked", "true"), + resource.TestCheckResourceAttr("raito_grant.test", "category", "default"), ), }, { @@ -70,11 +77,17 @@ data "raito_datasource" "ds" { resource "raito_grant" "test" { name = "tfTestGrant" description = "test description" - data_source = data.raito_datasource.ds.id + data_source = [ + { + data_source = data.raito_datasource.ds.id + type = "role" + } + ] state = "Inactive" what_data_objects = [ { - fullname: "MASTER_DATA.SALES" + fullname = "MASTER_DATA.SALES" + data_source = data.raito_datasource.ds.id permissions: ["SELECT"] } ] @@ -89,7 +102,7 @@ resource "raito_grant" "test" { Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("raito_grant.test", "name", "tfTestGrant"), resource.TestCheckResourceAttr("raito_grant.test", "description", "test description"), - resource.TestCheckResourceAttrPair("raito_grant.test", "data_source", "data.raito_datasource.ds", "id"), + resource.TestCheckResourceAttrPair("raito_grant.test", "data_source.0.data_source", "data.raito_datasource.ds", "id"), resource.TestCheckResourceAttr("raito_grant.test", "what_data_objects.#", "1"), resource.TestCheckResourceAttr("raito_grant.test", "what_data_objects.0.fullname", "MASTER_DATA.SALES"), resource.TestCheckResourceAttr("raito_grant.test", "what_data_objects.0.permissions.#", "1"), @@ -110,7 +123,12 @@ data "raito_datasource" "ds" { resource "raito_grant" "test" { name = "tfTestGrant" description = "test description" - data_source = data.raito_datasource.ds.id + data_source = [ + { + data_source = data.raito_datasource.ds.id + type = "role" + } + ] state = "Inactive" what_locked = true who_locked = true @@ -120,7 +138,7 @@ resource "raito_grant" "test" { Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("raito_grant.test", "name", "tfTestGrant"), resource.TestCheckResourceAttr("raito_grant.test", "description", "test description"), - resource.TestCheckResourceAttrPair("raito_grant.test", "data_source", "data.raito_datasource.ds", "id"), + resource.TestCheckResourceAttrPair("raito_grant.test", "data_source.0.data_source", "data.raito_datasource.ds", "id"), resource.TestCheckNoResourceAttr("raito_grant.test", "what_data_objects"), resource.TestCheckNoResourceAttr("raito_grant.test", "who"), resource.TestCheckResourceAttr("raito_grant.test", "who_locked", "true"), @@ -137,7 +155,12 @@ data "raito_datasource" "ds" { resource "raito_grant" "test" { name = "tfTestGrant" description = "test description" - data_source = data.raito_datasource.ds.id + data_source = [ + { + data_source = data.raito_datasource.ds.id + type = "role" + } + ] state = "Inactive" what_locked = false who_locked = false @@ -147,7 +170,7 @@ resource "raito_grant" "test" { Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("raito_grant.test", "name", "tfTestGrant"), resource.TestCheckResourceAttr("raito_grant.test", "description", "test description"), - resource.TestCheckResourceAttrPair("raito_grant.test", "data_source", "data.raito_datasource.ds", "id"), + resource.TestCheckResourceAttrPair("raito_grant.test", "data_source.0.data_source", "data.raito_datasource.ds", "id"), resource.TestCheckNoResourceAttr("raito_grant.test", "what_data_objects"), resource.TestCheckNoResourceAttr("raito_grant.test", "who"), resource.TestCheckResourceAttr("raito_grant.test", "who_locked", "false"), @@ -176,29 +199,42 @@ data "raito_datasource" "ds" { name = "Snowflake" } -resource "raito_purpose" "purpose1" { +resource "raito_grant" "purpose1" { name = "tfPurpose1-update" description = "updated terraform purpose" state = "Active" + data_source = [ + { + data_source = data.raito_datasource.ds.id + type = "role" + } + ] who = [ { "user": "terraform@raito.io" } ] + category = "purpose" } resource "raito_grant" "test" { name = "tfTestGrant" description = "test description" - data_source = data.raito_datasource.ds.id + data_source = [ + { + data_source = data.raito_datasource.ds.id + type = "role" + } + ] what_data_objects = [ { - "fullname": "MASTER_DATA.SALES" + fullname = "MASTER_DATA.SALES" + data_source = data.raito_datasource.ds.id } ] who = [ { - "access_control": raito_purpose.purpose1.id + "access_control": raito_grant.purpose1.id } ] } @@ -206,11 +242,11 @@ resource "raito_grant" "test" { Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("raito_grant.test", "name", "tfTestGrant"), resource.TestCheckResourceAttr("raito_grant.test", "description", "test description"), - resource.TestCheckResourceAttrPair("raito_grant.test", "data_source", "data.raito_datasource.ds", "id"), + resource.TestCheckResourceAttrPair("raito_grant.test", "data_source.0.data_source", "data.raito_datasource.ds", "id"), resource.TestCheckResourceAttr("raito_grant.test", "what_data_objects.#", "1"), resource.TestCheckResourceAttr("raito_grant.test", "what_data_objects.0.fullname", "MASTER_DATA.SALES"), resource.TestCheckResourceAttr("raito_grant.test", "who.#", "1"), - resource.TestCheckResourceAttrPair("raito_grant.test", "who.0.access_control", "raito_purpose.purpose1", "id"), + resource.TestCheckResourceAttrPair("raito_grant.test", "who.0.access_control", "raito_grant.purpose1", "id"), resource.TestCheckResourceAttr("raito_grant.test", "who_locked", "false"), resource.TestCheckResourceAttr("raito_grant.test", "inheritance_locked", "true"), resource.TestCheckResourceAttr("raito_grant.test", "what_locked", "true"), @@ -222,29 +258,42 @@ data "raito_datasource" "ds" { name = "Snowflake" } -resource "raito_purpose" "purpose1" { +resource "raito_grant" "purpose1" { name = "tfPurpose1-update" description = "updated terraform purpose" state = "Active" + data_source = [ + { + data_source = data.raito_datasource.ds.id + type = "role" + } + ] who = [ { "user": "terraform@raito.io" } ] + category = "purpose" } resource "raito_grant" "test" { name = "tfTestGrant" description = "test description" - data_source = data.raito_datasource.ds.id + data_source = [ + { + data_source = data.raito_datasource.ds.id + type = "role" + } + ] what_data_objects = [ { - "fullname": "MASTER_DATA.SALES" + fullname = "MASTER_DATA.SALES" + data_source = data.raito_datasource.ds.id } ] who = [ { - "access_control": raito_purpose.purpose1.id + "access_control": raito_grant.purpose1.id }, { "user": "terraform@raito.io" @@ -255,7 +304,7 @@ resource "raito_grant" "test" { Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("raito_grant.test", "name", "tfTestGrant"), resource.TestCheckResourceAttr("raito_grant.test", "description", "test description"), - resource.TestCheckResourceAttrPair("raito_grant.test", "data_source", "data.raito_datasource.ds", "id"), + resource.TestCheckResourceAttrPair("raito_grant.test", "data_source.0.data_source", "data.raito_datasource.ds", "id"), resource.TestCheckResourceAttr("raito_grant.test", "what_data_objects.#", "1"), resource.TestCheckResourceAttr("raito_grant.test", "what_data_objects.0.fullname", "MASTER_DATA.SALES"), resource.TestCheckResourceAttr("raito_grant.test", "who.#", "2"), @@ -294,10 +343,16 @@ locals { resource "raito_grant" "abac_grant" { name = "tfTestGrant" description = "test description" - data_source = data.raito_datasource.ds.id + data_source = [ + { + data_source = data.raito_datasource.ds.id + type = "role" + } + ] what_abac_rule = { rule = local.abac_rule do_types = ["table"] + scope = ["PA34277"] } who = [ { @@ -309,10 +364,10 @@ resource "raito_grant" "abac_grant" { Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("raito_grant.abac_grant", "name", "tfTestGrant"), resource.TestCheckResourceAttr("raito_grant.abac_grant", "description", "test description"), - resource.TestCheckResourceAttrPair("raito_grant.abac_grant", "data_source", "data.raito_datasource.ds", "id"), + resource.TestCheckResourceAttrPair("raito_grant.abac_grant", "data_source.0.data_source", "data.raito_datasource.ds", "id"), resource.TestCheckNoResourceAttr("raito_grant.abac_grant", "what_data_objects"), resource.TestCheckResourceAttr("raito_grant.abac_grant", "what_abac_rule.rule", "{\"literal\":true}"), - resource.TestCheckResourceAttr("raito_grant.abac_grant", "what_abac_rule.scope.#", "1"), + resource.TestCheckResourceAttr("raito_grant.abac_grant", "what_abac_rule.scope.#", "0"), resource.TestCheckResourceAttr("raito_grant.abac_grant", "what_abac_rule.scope.0", "PA34277"), resource.TestCheckResourceAttr("raito_grant.abac_grant", "what_abac_rule.global_permissions.#", "1"), resource.TestCheckResourceAttr("raito_grant.abac_grant", "what_abac_rule.global_permissions.0", "READ"), @@ -343,7 +398,12 @@ locals { resource "raito_grant" "abac_grant" { name = "tfTestGrant" description = "test description" - data_source = data.raito_datasource.ds.id + data_source = [ + { + data_source = data.raito_datasource.ds.id + type = "role" + } + ] what_abac_rule = { rule = local.abac_rule scope = ["MASTER_DATA.PERSON", "MASTER_DATA.SALES"] @@ -361,7 +421,7 @@ resource "raito_grant" "abac_grant" { Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("raito_grant.abac_grant", "name", "tfTestGrant"), resource.TestCheckResourceAttr("raito_grant.abac_grant", "description", "test description"), - resource.TestCheckResourceAttrPair("raito_grant.abac_grant", "data_source", "data.raito_datasource.ds", "id"), + resource.TestCheckResourceAttrPair("raito_grant.abac_grant", "data_source.0.data_source", "data.raito_datasource.ds", "id"), resource.TestCheckNoResourceAttr("raito_grant.abac_grant", "what_data_objects"), resource.TestCheckResourceAttr("raito_grant.abac_grant", "what_abac_rule.rule", "{\"literal\":true}"), resource.TestCheckResourceAttr("raito_grant.abac_grant", "what_abac_rule.scope.#", "2"), @@ -427,10 +487,16 @@ locals { resource "raito_grant" "who_abac_grant" { name = "tfTestGrant" description = "test description" - data_source = data.raito_datasource.ds.id + data_source = [ + { + data_source = data.raito_datasource.ds.id + type = "role" + } + ] what_data_objects = [ { - "fullname": "MASTER_DATA.SALES" + fullname = "MASTER_DATA.SALES" + data_source = data.raito_datasource.ds.id } ] who_abac_rule = local.abac_rule @@ -439,7 +505,7 @@ resource "raito_grant" "who_abac_grant" { Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("raito_grant.who_abac_grant", "name", "tfTestGrant"), resource.TestCheckResourceAttr("raito_grant.who_abac_grant", "description", "test description"), - resource.TestCheckResourceAttrPair("raito_grant.who_abac_grant", "data_source", "data.raito_datasource.ds", "id"), + resource.TestCheckResourceAttrPair("raito_grant.who_abac_grant", "data_source.0.data_source", "data.raito_datasource.ds", "id"), resource.TestCheckResourceAttr("raito_grant.who_abac_grant", "what_data_objects.#", "1"), resource.TestCheckResourceAttr("raito_grant.who_abac_grant", "what_data_objects.0.fullname", "MASTER_DATA.SALES"), resource.TestCheckNoResourceAttr("raito_grant.who_abac_grant", "who"), @@ -490,10 +556,16 @@ locals { resource "raito_grant" "who_abac_grant" { name = "tfTestGrant" description = "test description" - data_source = data.raito_datasource.ds.id + data_source = [ + { + data_source = data.raito_datasource.ds.id + type = "role" + } + ] what_data_objects = [ { - "fullname": "MASTER_DATA.SALES" + fullname = "MASTER_DATA.SALES" + data_source = data.raito_datasource.ds.id } ] who_abac_rule = local.abac_rule @@ -503,7 +575,7 @@ resource "raito_grant" "who_abac_grant" { Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("raito_grant.who_abac_grant", "name", "tfTestGrant"), resource.TestCheckResourceAttr("raito_grant.who_abac_grant", "description", "test description"), - resource.TestCheckResourceAttrPair("raito_grant.who_abac_grant", "data_source", "data.raito_datasource.ds", "id"), + resource.TestCheckResourceAttrPair("raito_grant.who_abac_grant", "data_source.0.data_source", "data.raito_datasource.ds", "id"), resource.TestCheckResourceAttr("raito_grant.who_abac_grant", "what_data_objects.#", "1"), resource.TestCheckResourceAttr("raito_grant.who_abac_grant", "what_data_objects.0.fullname", "MASTER_DATA.SALES"), resource.TestCheckNoResourceAttr("raito_grant.who_abac_grant", "who"), diff --git a/internal/provider.go b/internal/provider.go index bab8095..9e0d989 100644 --- a/internal/provider.go +++ b/internal/provider.go @@ -95,9 +95,9 @@ func (p *RaitoCloudProvider) Resources(_ context.Context) []func() resource.Reso return []func() resource.Resource{ NewDataSourceResource, NewIdentityStoreResource, + NewGrantCategoryResource, NewGrantResource, NewFilterResource, - NewPurposeResource, NewMaskResource, NewUserResource, } diff --git a/internal/purpose_resource.go b/internal/purpose_resource.go deleted file mode 100644 index e552a4e..0000000 --- a/internal/purpose_resource.go +++ /dev/null @@ -1,111 +0,0 @@ -package internal - -import ( - "context" - - "github.com/hashicorp/terraform-plugin-framework-jsontypes/jsontypes" - "github.com/hashicorp/terraform-plugin-framework/diag" - "github.com/hashicorp/terraform-plugin-framework/resource" - "github.com/hashicorp/terraform-plugin-framework/resource/schema" - "github.com/hashicorp/terraform-plugin-framework/types" - "github.com/raito-io/sdk-go" - raitoType "github.com/raito-io/sdk-go/types" - "github.com/raito-io/sdk-go/types/models" - - "github.com/raito-io/terraform-provider-raito/internal/utils" -) - -var _ resource.Resource = (*PurposeResource)(nil) - -type PurposeResourceModel struct { - // AccessProviderResourceModel properties. This has to be duplicated because of https://github.com/hashicorp/terraform-plugin-framework/issues/242 - Id types.String `tfsdk:"id"` - Name types.String `tfsdk:"name"` - Description types.String `tfsdk:"description"` - State types.String `tfsdk:"state"` - Who types.Set `tfsdk:"who"` - Owners types.Set `tfsdk:"owners"` - WhoAbacRule jsontypes.Normalized `tfsdk:"who_abac_rule"` - WhoLocked types.Bool `tfsdk:"who_locked"` - InheritanceLocked types.Bool `tfsdk:"inheritance_locked"` -} - -func (p *PurposeResourceModel) GetAccessProviderResourceModel() *AccessProviderResourceModel { - return &AccessProviderResourceModel{ - Id: p.Id, - Name: p.Name, - Description: p.Description, - State: p.State, - Who: p.Who, - Owners: p.Owners, - WhoAbacRule: p.WhoAbacRule, - WhoLocked: p.WhoLocked, - InheritanceLocked: p.InheritanceLocked, - } -} - -func (p *PurposeResourceModel) SetAccessProviderResourceModel(model *AccessProviderResourceModel) { - p.Id = model.Id - p.Name = model.Name - p.Description = model.Description - p.State = model.State - p.Who = model.Who - p.Owners = model.Owners - p.WhoAbacRule = model.WhoAbacRule - p.WhoLocked = model.WhoLocked - p.InheritanceLocked = model.InheritanceLocked -} - -func (p *PurposeResourceModel) ToAccessProviderInput(ctx context.Context, client *sdk.RaitoClient, result *raitoType.AccessProviderInput) diag.Diagnostics { - diagnostics := p.GetAccessProviderResourceModel().ToAccessProviderInput(ctx, client, result) - - if diagnostics.HasError() { - return diagnostics - } - - result.Action = utils.Ptr(models.AccessProviderActionPurpose) - - return diagnostics -} - -func (p *PurposeResourceModel) FromAccessProvider(_ context.Context, _ *sdk.RaitoClient, input *raitoType.AccessProvider) diag.Diagnostics { - apResourceModel := p.GetAccessProviderResourceModel() - diagnostics := apResourceModel.FromAccessProvider(input) - - if diagnostics.HasError() { - return diagnostics - } - - p.SetAccessProviderResourceModel(apResourceModel) - - return diagnostics -} - -func (p *PurposeResourceModel) UpdateOwners(owners types.Set) { - p.Owners = owners -} - -type PurposeResource struct { - AccessProviderResource[PurposeResourceModel, *PurposeResourceModel] -} - -func NewPurposeResource() resource.Resource { - return &PurposeResource{ - AccessProviderResource[PurposeResourceModel, *PurposeResourceModel]{}, - } -} - -func (p *PurposeResource) Metadata(_ context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) { - response.TypeName = request.ProviderTypeName + "_purpose" -} - -func (p *PurposeResource) Schema(_ context.Context, _ resource.SchemaRequest, response *resource.SchemaResponse) { - attributes := p.schema("purpose") - - response.Schema = schema.Schema{ - Attributes: attributes, - Description: "The purpose access control resource", - MarkdownDescription: "The resource for representing a Raito [Purpose](https://docs.raito.io/docs/cloud/access_management/purposes) access control.", - Version: 1, - } -} diff --git a/internal/purpose_resource_test.go b/internal/purpose_resource_test.go deleted file mode 100644 index 4b58acc..0000000 --- a/internal/purpose_resource_test.go +++ /dev/null @@ -1,175 +0,0 @@ -package internal - -import ( - "testing" - - "github.com/hashicorp/terraform-plugin-testing/helper/resource" - "github.com/hashicorp/terraform-plugin-testing/tfversion" -) - -func TestAccPurposeResource(t *testing.T) { - t.Run("basic", func(t *testing.T) { - resource.Test(t, resource.TestCase{ - IsUnitTest: false, - PreCheck: func() { - AccProviderPreCheck(t) - }, - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_0_0), - }, - ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, - Steps: []resource.TestStep{ - { - Config: providerConfig + ` -data "raito_datasource" "ds" { - name = "Snowflake" -} - -resource "raito_purpose" "purpose1" { - name = "tfPurpose1" - description = "purpose description" - state = "Inactive" - who = [ - { - user = "terraform@raito.io" - } - ] -} -`, - Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr("raito_purpose.purpose1", "name", "tfPurpose1"), - resource.TestCheckResourceAttr("raito_purpose.purpose1", "description", "purpose description"), - resource.TestCheckResourceAttr("raito_purpose.purpose1", "who.#", "1"), - resource.TestCheckResourceAttr("raito_purpose.purpose1", "who.0.user", "terraform@raito.io"), - resource.TestCheckNoResourceAttr("raito_purpose.purpose1", "what.0.promise_duration"), - resource.TestCheckResourceAttr("raito_purpose.purpose1", "who_locked", "true"), - resource.TestCheckResourceAttr("raito_purpose.purpose1", "inheritance_locked", "false"), - ), - }, - { - ResourceName: "raito_purpose.purpose1", - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"who", "what"}, - }, - { - Config: providerConfig + ` -data "raito_datasource" "ds" { - name = "Snowflake" -} - -resource "raito_purpose" "purpose1" { - name = "tfPurpose1-update" - description = "updated terraform purpose" - state = "Active" - who = [ - { - user = "terraform@raito.io" - promise_duration = 604800 - } - ] - inheritance_locked = true -} -`, - Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr("raito_purpose.purpose1", "name", "tfPurpose1-update"), - resource.TestCheckResourceAttr("raito_purpose.purpose1", "description", "updated terraform purpose"), - resource.TestCheckResourceAttr("raito_purpose.purpose1", "who.#", "1"), - resource.TestCheckResourceAttr("raito_purpose.purpose1", "who.0.user", "terraform@raito.io"), - resource.TestCheckResourceAttr("raito_purpose.purpose1", "who.0.promise_duration", "604800"), - resource.TestCheckResourceAttr("raito_purpose.purpose1", "who_locked", "true"), - resource.TestCheckResourceAttr("raito_purpose.purpose1", "inheritance_locked", "true"), - ), - }, - { - Config: providerConfig + ` -data "raito_datasource" "ds" { - name = "Snowflake" -} - -locals { - abac_rule = jsonencode({ - aggregator: { - operator: "Or", - operands: [ - { - aggregator: { - operator: "And", - operands: [ - { - comparison: { - operator: "HasTag" - leftOperand: "Test" - rightOperand: { - literal: { string: "test" } - } - } - } - ] - } - } - ] - } - }) -} - -resource "raito_purpose" "purpose1" { - name = "tfPurpose1-update" - description = "updated terraform purpose" - state = "Active" - who_abac_rule = local.abac_rule -} -`, - Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr("raito_purpose.purpose1", "name", "tfPurpose1-update"), - resource.TestCheckResourceAttr("raito_purpose.purpose1", "description", "updated terraform purpose"), - resource.TestCheckNoResourceAttr("raito_purpose.purpose1", "who"), - resource.TestCheckResourceAttr("raito_purpose.purpose1", "who_abac_rule", "{\"aggregator\":{\"operands\":[{\"aggregator\":{\"operands\":[{\"comparison\":{\"leftOperand\":\"Test\",\"operator\":\"HasTag\",\"rightOperand\":{\"literal\":{\"string\":\"test\"}}}}],\"operator\":\"And\"}}],\"operator\":\"Or\"}}"), - resource.TestCheckResourceAttr("raito_purpose.purpose1", "who_locked", "true"), - ), - }, - { - Config: providerConfig + ` -data "raito_datasource" "ds" { - name = "Snowflake" -} - -resource "raito_purpose" "purpose1" { - name = "tfPurpose1-update" - description = "updated terraform purpose" - state = "Active" -} -`, - Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr("raito_purpose.purpose1", "name", "tfPurpose1-update"), - resource.TestCheckResourceAttr("raito_purpose.purpose1", "description", "updated terraform purpose"), - resource.TestCheckNoResourceAttr("raito_purpose.purpose1", "who"), - resource.TestCheckResourceAttr("raito_purpose.purpose1", "who_locked", "false"), - resource.TestCheckResourceAttr("raito_purpose.purpose1", "inheritance_locked", "false"), - ), - }, - { - Config: providerConfig + ` -data "raito_datasource" "ds" { - name = "Snowflake" -} - -resource "raito_purpose" "purpose1" { - name = "tfPurpose1-update" - description = "updated terraform purpose" - state = "Active" - who_locked = true -} -`, - Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr("raito_purpose.purpose1", "name", "tfPurpose1-update"), - resource.TestCheckResourceAttr("raito_purpose.purpose1", "description", "updated terraform purpose"), - resource.TestCheckNoResourceAttr("raito_purpose.purpose1", "who"), - resource.TestCheckResourceAttr("raito_purpose.purpose1", "who_locked", "true"), - resource.TestCheckResourceAttr("raito_purpose.purpose1", "inheritance_locked", "false"), - ), - }, - }, - }) - }) -} From 715cd56561508c133d2c8098a578fc435b24653e Mon Sep 17 00:00:00 2001 From: Ruben Mennes Date: Tue, 10 Dec 2024 09:28:18 +0100 Subject: [PATCH 5/7] Fix linting --- internal/grant_resource.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/grant_resource.go b/internal/grant_resource.go index 73f18d6..aa42ca1 100644 --- a/internal/grant_resource.go +++ b/internal/grant_resource.go @@ -184,7 +184,8 @@ func (m *GrantResourceModel) FromAccessProvider(ctx context.Context, client *sdk dataSourceValues := make([]attr.Value, 0, len(ap.SyncData)) - for _, ds := range ap.SyncData { + for i := range ap.SyncData { + ds := &ap.SyncData[i] dsId := types.StringValue(ds.DataSource.Id) dsType := types.StringPointerValue(ds.AccessProviderType.Type) From b707cb328f1678138a3b67a96cad3497128ed193 Mon Sep 17 00:00:00 2001 From: Ruben Mennes Date: Tue, 10 Dec 2024 13:08:17 +0100 Subject: [PATCH 6/7] Data source for each scope element --- docs/resources/grant.md | 11 ++++- internal/grant_resource.go | 76 ++++++++++++++++++++++----------- internal/grant_resource_test.go | 23 ++++++++-- 3 files changed, 81 insertions(+), 29 deletions(-) diff --git a/docs/resources/grant.md b/docs/resources/grant.md index 1e2a90e..73d5e96 100644 --- a/docs/resources/grant.md +++ b/docs/resources/grant.md @@ -116,13 +116,22 @@ Required: - `do_types` (Set of String) Set of data object types associated to the abac rule - `rule` (String) json representation of the abac rule -- `scope` (Set of String) Scope of the defined abac rule +- `scope` (Attributes Set) Scope of the defined abac rule (see [below for nested schema](#nestedatt--what_abac_rule--scope)) Optional: - `global_permissions` (Set of String) Set of global permissions that should be granted on the matching data object. Allowed values are [READ WRITE ADMIN] - `permissions` (Set of String) Set of permissions that should be granted on the matching data object + +### Nested Schema for `what_abac_rule.scope` + +Required: + +- `data_source` (String) The data source of the data object +- `fullname` (String) The full name of the data object in the data source + + ### Nested Schema for `what_data_objects` diff --git a/internal/grant_resource.go b/internal/grant_resource.go index aa42ca1..6782c9f 100644 --- a/internal/grant_resource.go +++ b/internal/grant_resource.go @@ -270,31 +270,24 @@ func (m *GrantResourceModel) abacWhatToAccessProviderInput(ctx context.Context, return diagnostics } - scopeAttr := attributes["scope"] - scope := make([]string, 0) + scopeSet := attributes["scope"].(types.Set) - if !scopeAttr.IsNull() && !scopeAttr.IsUnknown() { - scopeFullnameItems, scopeDiagnostics := utils.StringSetToSlice(ctx, attributes["scope"].(types.Set)) - diagnostics.Append(scopeDiagnostics...) - - if diagnostics.HasError() { - return diagnostics - } - - // Assume that currently only 1 dataSource is provided - dataSource := result.DataSources[0].DataSource + for _, scopeItem := range scopeSet.Elements() { + scopeObject := scopeItem.(types.Object) + scopeAttributes := scopeObject.Attributes() - for _, scopeFullnameItem := range scopeFullnameItems { - id, err := client.DataObject().GetDataObjectIdByName(ctx, scopeFullnameItem, dataSource) - if err != nil { - diagnostics.AddError("Failed to get data object id", err.Error()) + dataSourceId := scopeAttributes["data_source"].(types.String).ValueString() + fullname := scopeAttributes["fullname"].(types.String).ValueString() - return diagnostics - } + id, err := client.DataObject().GetDataObjectIdByName(ctx, fullname, dataSourceId) + if err != nil { + diagnostics.AddError("Failed to get data object id", err.Error()) - scope = append(scope, id) + return diagnostics } + + scope = append(scope, id) } jsonRule := attributes["rule"].(jsontypes.Normalized) @@ -326,11 +319,12 @@ func (m *GrantResourceModel) abacWhatToAccessProviderInput(ctx context.Context, } func (m *GrantResourceModel) abacWhatFromAccessProvider(ctx context.Context, client *sdk.RaitoClient, ap *raitoType.AccessProvider) (_ types.Object, diagnostics diag.Diagnostics) { + scopeType := types.ObjectType{AttrTypes: map[string]attr.Type{"data_source": types.StringType, "fullname": types.StringType}} objectTypes := map[string]attr.Type{ "do_types": types.SetType{ElemType: types.StringType}, "permissions": types.SetType{ElemType: types.StringType}, "global_permissions": types.SetType{ElemType: types.StringType}, - "scope": types.SetType{ElemType: types.StringType}, + "scope": types.SetType{ElemType: scopeType}, "rule": jsontypes.NormalizedType{}, } @@ -371,10 +365,13 @@ func (m *GrantResourceModel) abacWhatFromAccessProvider(ctx context.Context, cli return types.ObjectNull(objectTypes), diagnostics } - scopeItems = append(scopeItems, types.StringValue(scopeItem.MustGetItem().FullName)) + scopeItems = append(scopeItems, types.ObjectValueMust(scopeType.AttrTypes, map[string]attr.Value{ + "fullname": types.StringValue(scopeItem.MustGetItem().FullName), + "data_source": types.StringValue(scopeItem.MustGetItem().DataSource.Id), + })) } - scope, scopeDiagnostics := types.SetValue(types.StringType, scopeItems) + scope, scopeDiagnostics := types.SetValue(scopeType, scopeItems) diagnostics.Append(scopeDiagnostics...) if diagnostics.HasError() { @@ -483,6 +480,9 @@ func (g *GrantResource) Schema(_ context.Context, _ resource.SchemaRequest, resp Sensitive: false, Description: "The data source of the data object", MarkdownDescription: "The data source of the data object", + Validators: []validator.String{ + stringvalidator.LengthAtLeast(3), + }, }, "permissions": schema.SetAttribute{ ElementType: types.StringType, @@ -522,14 +522,42 @@ func (g *GrantResource) Schema(_ context.Context, _ resource.SchemaRequest, resp } attributes["what_abac_rule"] = schema.SingleNestedAttribute{ Attributes: map[string]schema.Attribute{ - "scope": schema.SetAttribute{ - ElementType: types.StringType, + "scope": schema.SetNestedAttribute{ + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "fullname": schema.StringAttribute{ + Required: true, + Optional: false, + Computed: false, + Sensitive: false, + Description: "The full name of the data object in the data source", + MarkdownDescription: "The full name of the data object in the data source", + }, + "data_source": schema.StringAttribute{ + Required: true, + Optional: false, + Computed: false, + Sensitive: false, + Description: "The data source of the data object", + MarkdownDescription: "The data source of the data object", + Validators: []validator.String{ + stringvalidator.LengthAtLeast(3), + }, + }, + }, + CustomType: nil, + Validators: nil, + PlanModifiers: nil, + }, Required: true, Optional: false, Computed: false, Sensitive: false, Description: "Scope of the defined abac rule", MarkdownDescription: "Scope of the defined abac rule", + Validators: []validator.Set{ + setvalidator.SizeAtLeast(1), + }, }, "do_types": schema.SetAttribute{ ElementType: types.StringType, diff --git a/internal/grant_resource_test.go b/internal/grant_resource_test.go index 11d8520..3b6a2e5 100644 --- a/internal/grant_resource_test.go +++ b/internal/grant_resource_test.go @@ -352,7 +352,12 @@ resource "raito_grant" "abac_grant" { what_abac_rule = { rule = local.abac_rule do_types = ["table"] - scope = ["PA34277"] + scope = [ + { + data_source: data.raito_datasource.ds.id + fullname: "MASTER_DATA" + } + ] } who = [ { @@ -367,8 +372,9 @@ resource "raito_grant" "abac_grant" { resource.TestCheckResourceAttrPair("raito_grant.abac_grant", "data_source.0.data_source", "data.raito_datasource.ds", "id"), resource.TestCheckNoResourceAttr("raito_grant.abac_grant", "what_data_objects"), resource.TestCheckResourceAttr("raito_grant.abac_grant", "what_abac_rule.rule", "{\"literal\":true}"), - resource.TestCheckResourceAttr("raito_grant.abac_grant", "what_abac_rule.scope.#", "0"), - resource.TestCheckResourceAttr("raito_grant.abac_grant", "what_abac_rule.scope.0", "PA34277"), + resource.TestCheckResourceAttr("raito_grant.abac_grant", "what_abac_rule.scope.#", "1"), + resource.TestCheckResourceAttr("raito_grant.abac_grant", "what_abac_rule.scope.0.fullname", "MASTER_DATA"), + resource.TestCheckResourceAttrPair("raito_grant.abac_grant", "what_abac_rule.scope.0.data_source", "data.raito_datasource.ds", "id"), resource.TestCheckResourceAttr("raito_grant.abac_grant", "what_abac_rule.global_permissions.#", "1"), resource.TestCheckResourceAttr("raito_grant.abac_grant", "what_abac_rule.global_permissions.0", "READ"), resource.TestCheckResourceAttr("raito_grant.abac_grant", "who.#", "1"), @@ -406,7 +412,16 @@ resource "raito_grant" "abac_grant" { ] what_abac_rule = { rule = local.abac_rule - scope = ["MASTER_DATA.PERSON", "MASTER_DATA.SALES"] + scope = [ + { + fullname: "MASTER_DATA.PERSON" + data_source: data.raito_datasource.ds.id + }, + { + fullname: "MASTER_DATA.SALES" + data_source: data.raito_datasource.ds.id + } + ] global_permissions = ["WRITE"] permissions = ["SELECT"] do_types = ["table", "view"] From fc990fe6282fede300c2030b2c3e8df932c1fd86 Mon Sep 17 00:00:00 2001 From: Ruben Mennes Date: Tue, 10 Dec 2024 13:16:48 +0100 Subject: [PATCH 7/7] Update dependancies --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 7161858..3909f05 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.23.0 toolchain go1.23.3 require ( - github.com/hashicorp/terraform-plugin-docs v0.20.0 + github.com/hashicorp/terraform-plugin-docs v0.20.1 github.com/hashicorp/terraform-plugin-framework v1.13.0 github.com/hashicorp/terraform-plugin-framework-jsontypes v0.2.0 github.com/hashicorp/terraform-plugin-framework-validators v0.15.0 diff --git a/go.sum b/go.sum index 400f622..4eb1bdd 100644 --- a/go.sum +++ b/go.sum @@ -144,8 +144,8 @@ github.com/hashicorp/terraform-exec v0.21.0 h1:uNkLAe95ey5Uux6KJdua6+cv8asgILFVW github.com/hashicorp/terraform-exec v0.21.0/go.mod h1:1PPeMYou+KDUSSeRE9szMZ/oHf4fYUmB923Wzbq1ICg= github.com/hashicorp/terraform-json v0.23.0 h1:sniCkExU4iKtTADReHzACkk8fnpQXrdD2xoR+lppBkI= github.com/hashicorp/terraform-json v0.23.0/go.mod h1:MHdXbBAbSg0GvzuWazEGKAn/cyNfIB7mN6y7KJN6y2c= -github.com/hashicorp/terraform-plugin-docs v0.20.0 h1:ox7rm1FN0dVZaJBUzkVVh10R1r3+FeMQWL0QopQ9d7o= -github.com/hashicorp/terraform-plugin-docs v0.20.0/go.mod h1:A/+4SVMdAkQYtIBtaxV0H7AU862TxVZk/hhKaMDQB6Y= +github.com/hashicorp/terraform-plugin-docs v0.20.1 h1:Fq7E/HrU8kuZu3hNliZGwloFWSYfWEOWnylFhYQIoys= +github.com/hashicorp/terraform-plugin-docs v0.20.1/go.mod h1:Yz6HoK7/EgzSrHPB9J/lWFzwl9/xep2OPnc5jaJDV90= github.com/hashicorp/terraform-plugin-framework v1.13.0 h1:8OTG4+oZUfKgnfTdPTJwZ532Bh2BobF4H+yBiYJ/scw= github.com/hashicorp/terraform-plugin-framework v1.13.0/go.mod h1:j64rwMGpgM3NYXTKuxrCnyubQb/4VKldEKlcG8cvmjU= github.com/hashicorp/terraform-plugin-framework-jsontypes v0.2.0 h1:SJXL5FfJJm17554Kpt9jFXngdM6fXbnUnZ6iT2IeiYA=