diff --git a/docs/resources/compliance_relationship.md b/docs/resources/compliance_relationship.md new file mode 100644 index 00000000..8a6ff914 --- /dev/null +++ b/docs/resources/compliance_relationship.md @@ -0,0 +1,28 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "jupiterone_compliance_relationship Resource - terraform-provider-jupiterone" +subcategory: "" +description: |- + A relationship between a framework item (requirement) and a library item (control). +--- + +# jupiterone_compliance_relationship (Resource) + +A relationship between a framework item (requirement) and a library item (control). + + + + +## Schema + +### Required + +- `framework_item_id` (String) The id of the framework item (requirement) to link +- `library_item_id` (String) The id of the library item (control) to link +- `relationship_type` (String) Whether to INHERIT_EVIDENCE or IGNORE_EVIDENCE in the linked framework item + +### Read-Only + +- `id` (String) The ID of this resource. + + diff --git a/go.mod b/go.mod index 096af6b2..15302759 100644 --- a/go.mod +++ b/go.mod @@ -9,12 +9,12 @@ require ( github.com/hashicorp/go-cleanhttp v0.5.2 github.com/hashicorp/go-hclog v1.5.0 github.com/hashicorp/terraform-plugin-docs v0.13.0 - github.com/hashicorp/terraform-plugin-framework v1.3.2 + github.com/hashicorp/terraform-plugin-framework v1.3.5 github.com/hashicorp/terraform-plugin-framework-validators v0.9.0 - github.com/hashicorp/terraform-plugin-go v0.17.0 + github.com/hashicorp/terraform-plugin-go v0.18.0 github.com/hashicorp/terraform-plugin-log v0.9.0 - github.com/hashicorp/terraform-plugin-sdk/v2 v2.27.0 - github.com/hashicorp/terraform-plugin-testing v1.3.0 + github.com/hashicorp/terraform-plugin-sdk/v2 v2.28.0 + github.com/hashicorp/terraform-plugin-testing v1.5.1 github.com/stretchr/testify v1.8.1 gopkg.in/dnaeon/go-vcr.v3 v3.1.2 ) @@ -103,7 +103,7 @@ require ( github.com/hashicorp/hcl/v2 v2.17.0 // indirect github.com/hashicorp/logutils v1.0.0 // indirect github.com/hashicorp/terraform-exec v0.18.1 // indirect - github.com/hashicorp/terraform-json v0.17.0 // indirect + github.com/hashicorp/terraform-json v0.17.1 // indirect github.com/hashicorp/terraform-registry-address v0.2.1 // indirect github.com/hashicorp/terraform-svchost v0.1.1 // indirect github.com/hashicorp/yamux v0.1.1 // indirect @@ -199,15 +199,16 @@ require ( github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/yagipy/maintidx v1.0.0 // indirect github.com/yeya24/promlinter v0.2.0 // indirect - github.com/zclconf/go-cty v1.13.2 // indirect + github.com/zclconf/go-cty v1.13.3 // indirect gitlab.com/bosi/decorder v0.2.1 // indirect - golang.org/x/crypto v0.10.0 // indirect + golang.org/x/crypto v0.12.0 // indirect + golang.org/x/exp v0.0.0-20230809150735-7b3493d9a819 // indirect golang.org/x/exp/typeparams v0.0.0-20220218215828-6cf2b201936e // indirect - golang.org/x/mod v0.10.0 // indirect + golang.org/x/mod v0.11.0 // indirect golang.org/x/net v0.11.0 // indirect golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.9.0 // indirect - golang.org/x/text v0.10.0 // indirect + golang.org/x/sys v0.11.0 // indirect + golang.org/x/text v0.12.0 // indirect golang.org/x/tools v0.6.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect diff --git a/go.sum b/go.sum index b0510f14..709a34d7 100644 --- a/go.sum +++ b/go.sum @@ -495,22 +495,22 @@ github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpT github.com/hashicorp/serf v0.9.7/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= github.com/hashicorp/terraform-exec v0.18.1 h1:LAbfDvNQU1l0NOQlTuudjczVhHj061fNX5H8XZxHlH4= github.com/hashicorp/terraform-exec v0.18.1/go.mod h1:58wg4IeuAJ6LVsLUeD2DWZZoc/bYi6dzhLHzxM41980= -github.com/hashicorp/terraform-json v0.17.0 h1:EiA1Wp07nknYQAiv+jIt4dX4Cq5crgP+TsTE45MjMmM= -github.com/hashicorp/terraform-json v0.17.0/go.mod h1:Huy6zt6euxaY9knPAFKjUITn8QxUFIe9VuSzb4zn/0o= +github.com/hashicorp/terraform-json v0.17.1 h1:eMfvh/uWggKmY7Pmb3T85u86E2EQg6EQHgyRwf3RkyA= +github.com/hashicorp/terraform-json v0.17.1/go.mod h1:Huy6zt6euxaY9knPAFKjUITn8QxUFIe9VuSzb4zn/0o= github.com/hashicorp/terraform-plugin-docs v0.13.0 h1:6e+VIWsVGb6jYJewfzq2ok2smPzZrt1Wlm9koLeKazY= github.com/hashicorp/terraform-plugin-docs v0.13.0/go.mod h1:W0oCmHAjIlTHBbvtppWHe8fLfZ2BznQbuv8+UD8OucQ= -github.com/hashicorp/terraform-plugin-framework v1.3.2 h1:aQ6GSD0CTnvoALEWvKAkcH/d8jqSE0Qq56NYEhCexUs= -github.com/hashicorp/terraform-plugin-framework v1.3.2/go.mod h1:oimsRAPJOYkZ4kY6xIGfR0PHjpHLDLaknzuptl6AvnY= +github.com/hashicorp/terraform-plugin-framework v1.3.5 h1:FJ6s3CVWVAxlhiF/jhy6hzs4AnPHiflsp9KgzTGl1wo= +github.com/hashicorp/terraform-plugin-framework v1.3.5/go.mod h1:2gGDpWiTI0irr9NSTLFAKlTi6KwGti3AoU19rFqU30o= github.com/hashicorp/terraform-plugin-framework-validators v0.9.0 h1:LYz4bXh3t7bTEydXOmPDPupRRnA480B/9+jV8yZvxBA= github.com/hashicorp/terraform-plugin-framework-validators v0.9.0/go.mod h1:+BVERsnfdlhYR2YkXMBtPnmn9UsL19U3qUtSZ+Y/5MY= -github.com/hashicorp/terraform-plugin-go v0.17.0 h1:OpqgPLvjW3vCDA9VUEmRKppCZOG/+Vkdp6ijkG8aJek= -github.com/hashicorp/terraform-plugin-go v0.17.0/go.mod h1:l7VK+2u5Kf2y+A+742GX0ouLut3gttudmvMgN0PA74Y= +github.com/hashicorp/terraform-plugin-go v0.18.0 h1:IwTkOS9cOW1ehLd/rG0y+u/TGLK9y6fGoBjXVUquzpE= +github.com/hashicorp/terraform-plugin-go v0.18.0/go.mod h1:l7VK+2u5Kf2y+A+742GX0ouLut3gttudmvMgN0PA74Y= 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.27.0 h1:I8efBnjuDrgPjNF1MEypHy48VgcTIUY4X6rOFunrR3Y= -github.com/hashicorp/terraform-plugin-sdk/v2 v2.27.0/go.mod h1:cUEP4ly/nxlHy5HzD6YRrHydtlheGvGRJDhiWqqVik4= -github.com/hashicorp/terraform-plugin-testing v1.3.0 h1:4Pn8fSspPCRUc5zRGPNZYc00VhQmQPEH6y6Pv4e/42M= -github.com/hashicorp/terraform-plugin-testing v1.3.0/go.mod h1:mGOfGFTVIhP9buGPZyDQhmZFIO/Ig8E0Fo694UACr64= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.28.0 h1:gY4SG34ANc6ZSeWEKC9hDTChY0ZiN+Myon17fSA0Xgc= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.28.0/go.mod h1:deXEw/iJXtJxNV9d1c/OVJrvL7Zh0a++v7rzokW6wVY= +github.com/hashicorp/terraform-plugin-testing v1.5.1 h1:T4aQh9JAhmWo4+t1A7x+rnxAJHCDIYW9kXyo4sVO92c= +github.com/hashicorp/terraform-plugin-testing v1.5.1/go.mod h1:dg8clO6K59rZ8w9EshBmDp1CxTIPu3yA4iaDpX1h5u0= github.com/hashicorp/terraform-registry-address v0.2.1 h1:QuTf6oJ1+WSflJw6WYOHhLgwUiQ0FrROpHPYFtwTYWM= github.com/hashicorp/terraform-registry-address v0.2.1/go.mod h1:BSE9fIFzp0qWsJUUyGquo4ldV9k2n+psif6NYkBRS3Y= github.com/hashicorp/terraform-svchost v0.1.1 h1:EZZimZ1GxdqFRinZ1tpJwVxxt49xc/S52uzrw4x0jKQ= @@ -953,8 +953,8 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/zclconf/go-cty v1.13.2 h1:4GvrUxe/QUDYuJKAav4EYqdM47/kZa672LwmXFmEKT0= -github.com/zclconf/go-cty v1.13.2/go.mod h1:YKQzy/7pZ7iq2jNFzy5go57xdxdWoLLpaEp4u238AE0= +github.com/zclconf/go-cty v1.13.3 h1:m+b9q3YDbg6Bec5rr+KGy1MzEVzY/jC2X+YX4yqKtHI= +github.com/zclconf/go-cty v1.13.3/go.mod h1:YKQzy/7pZ7iq2jNFzy5go57xdxdWoLLpaEp4u238AE0= gitlab.com/bosi/decorder v0.2.1 h1:ehqZe8hI4w7O4b1vgsDZw1YU1PE7iJXrQWFMsocbQ1w= gitlab.com/bosi/decorder v0.2.1/go.mod h1:6C/nhLSbF6qZbYD8bRmISBwc6vcWdNsiIBkRvjJFrH0= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= @@ -1001,8 +1001,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220313003712-b769efc7c000/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM= -golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= +golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1014,6 +1014,8 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= +golang.org/x/exp v0.0.0-20230809150735-7b3493d9a819 h1:EDuYyU/MkFXllv9QF9819VlI9a4tzGuCbhG0ExK9o1U= +golang.org/x/exp v0.0.0-20230809150735-7b3493d9a819/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/exp/typeparams v0.0.0-20220218215828-6cf2b201936e h1:qyrTQ++p1afMkO4DPEeLGq/3oTsdlvdH4vqZUBWzUKM= golang.org/x/exp/typeparams v0.0.0-20220218215828-6cf2b201936e/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= @@ -1043,8 +1045,8 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= -golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= -golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU= +golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1230,12 +1232,12 @@ golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= -golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= 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.9.0 h1:GRRCnKYhdQrD8kfRAdQ6Zcw1P0OcELxGLKJvtjVMZ28= +golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1245,8 +1247,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58= -golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= +golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= diff --git a/jupiterone/cassettes/TestComplianceRelationship_Basic.yaml b/jupiterone/cassettes/TestComplianceRelationship_Basic.yaml new file mode 100644 index 00000000..5543603f --- /dev/null +++ b/jupiterone/cassettes/TestComplianceRelationship_Basic.yaml @@ -0,0 +1,939 @@ +--- +version: 2 +interactions: + - id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 341 + transfer_encoding: [] + trailer: {} + host: graphql.us.jupiterone.io + remote_addr: "" + request_uri: "" + body: '{"query":"\nmutation CreateComplianceFramework ($framework: CreateComplianceFrameworkInput!) {\n\tcreateComplianceFramework(input: $framework) {\n\t\tid\n\t}\n}\n","variables":{"framework":{"name":"tf-acc-test-framework","version":"1","frameworkType":"STANDARD","webLink":"","scopeFilters":null}},"operationName":"CreateComplianceFramework"}' + form: {} + headers: + Cache-Control: + - no-cache + Content-Type: + - application/json + url: https://graphql.us.jupiterone.io/ + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 85 + uncompressed: false + body: | + {"data":{"createComplianceFramework":{"id":"9e8595a7-6b6e-42cc-8a29-c80e85f9e899"}}} + headers: + Access-Control-Allow-Credentials: + - "true" + Content-Length: + - "85" + Content-Security-Policy: + - 'default-src ''self'';base-uri ''self'';block-all-mixed-content;font-src ''self'' https: data:;form-action ''self'';frame-ancestors ''self'';img-src ''self'' data:;object-src ''none'';script-src ''self'';script-src-attr ''none'';style-src ''self'' https: ''unsafe-inline'';upgrade-insecure-requests' + Content-Type: + - application/json + Cross-Origin-Embedder-Policy: + - require-corp + Cross-Origin-Opener-Policy: + - same-origin + Cross-Origin-Resource-Policy: + - same-origin + Expect-Ct: + - max-age=0 + Origin-Agent-Cluster: + - ?1 + Ratelimit-Limit: + - "1000" + Ratelimit-Remaining: + - "999" + Ratelimit-Requested: + - "1" + Ratelimit-Reset: + - "1" + Referrer-Policy: + - no-referrer + Strict-Transport-Security: + - max-age=15552000; includeSubDomains + Vary: + - Origin + X-Content-Type-Options: + - nosniff + X-Dns-Prefetch-Control: + - "off" + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Xss-Protection: + - "0" + status: 200 OK + code: 200 + duration: 1.790640916s + - id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 339 + transfer_encoding: [] + trailer: {} + host: graphql.us.jupiterone.io + remote_addr: "" + request_uri: "" + body: '{"query":"\nmutation CreateComplianceGroup ($input: CreateComplianceGroupInput!) {\n\tcreateComplianceGroup(input: $input) {\n\t\tid\n\t}\n}\n","variables":{"input":{"name":"tf-acc-test-group","description":"","displayCategory":"","frameworkId":"9e8595a7-6b6e-42cc-8a29-c80e85f9e899","webLink":""}},"operationName":"CreateComplianceGroup"}' + form: {} + headers: + Cache-Control: + - no-cache + Content-Type: + - application/json + url: https://graphql.us.jupiterone.io/ + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 81 + uncompressed: false + body: | + {"data":{"createComplianceGroup":{"id":"daee12fb-be37-461f-b9e3-9ad96d778159"}}} + headers: + Access-Control-Allow-Credentials: + - "true" + Content-Length: + - "81" + Content-Security-Policy: + - 'default-src ''self'';base-uri ''self'';block-all-mixed-content;font-src ''self'' https: data:;form-action ''self'';frame-ancestors ''self'';img-src ''self'' data:;object-src ''none'';script-src ''self'';script-src-attr ''none'';style-src ''self'' https: ''unsafe-inline'';upgrade-insecure-requests' + Content-Type: + - application/json + Cross-Origin-Embedder-Policy: + - require-corp + Cross-Origin-Opener-Policy: + - same-origin + Cross-Origin-Resource-Policy: + - same-origin + Expect-Ct: + - max-age=0 + Origin-Agent-Cluster: + - ?1 + Ratelimit-Limit: + - "1000" + Ratelimit-Remaining: + - "999" + Ratelimit-Requested: + - "1" + Ratelimit-Reset: + - "1" + Referrer-Policy: + - no-referrer + Strict-Transport-Security: + - max-age=15552000; includeSubDomains + Vary: + - Origin + X-Content-Type-Options: + - nosniff + X-Dns-Prefetch-Control: + - "off" + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Xss-Protection: + - "0" + status: 200 OK + code: 200 + duration: 1.15666s + - id: 2 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 428 + transfer_encoding: [] + trailer: {} + host: graphql.us.jupiterone.io + remote_addr: "" + request_uri: "" + body: '{"query":"\nmutation CreateComplianceFrameworkItem ($input: CreateComplianceFrameworkItemInput!) {\n\tcreateComplianceFrameworkItem(input: $input) {\n\t\tid\n\t}\n}\n","variables":{"input":{"name":"tf-acc-test-item","description":"","displayCategory":"","ref":"","frameworkId":"9e8595a7-6b6e-42cc-8a29-c80e85f9e899","groupId":"daee12fb-be37-461f-b9e3-9ad96d778159","webLink":""}},"operationName":"CreateComplianceFrameworkItem"}' + form: {} + headers: + Cache-Control: + - no-cache + Content-Type: + - application/json + url: https://graphql.us.jupiterone.io/ + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 89 + uncompressed: false + body: | + {"data":{"createComplianceFrameworkItem":{"id":"58bf83f7-77bd-40d6-864a-34dc10dd5577"}}} + headers: + Access-Control-Allow-Credentials: + - "true" + Content-Length: + - "89" + Content-Security-Policy: + - 'default-src ''self'';base-uri ''self'';block-all-mixed-content;font-src ''self'' https: data:;form-action ''self'';frame-ancestors ''self'';img-src ''self'' data:;object-src ''none'';script-src ''self'';script-src-attr ''none'';style-src ''self'' https: ''unsafe-inline'';upgrade-insecure-requests' + Content-Type: + - application/json + Cross-Origin-Embedder-Policy: + - require-corp + Cross-Origin-Opener-Policy: + - same-origin + Cross-Origin-Resource-Policy: + - same-origin + Expect-Ct: + - max-age=0 + Origin-Agent-Cluster: + - ?1 + Ratelimit-Limit: + - "1000" + Ratelimit-Remaining: + - "999" + Ratelimit-Requested: + - "1" + Ratelimit-Reset: + - "1" + Referrer-Policy: + - no-referrer + Strict-Transport-Security: + - max-age=15552000; includeSubDomains + Vary: + - Origin + X-Content-Type-Options: + - nosniff + X-Dns-Prefetch-Control: + - "off" + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Xss-Protection: + - "0" + status: 200 OK + code: 200 + duration: 3.044858917s + - id: 3 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 321 + transfer_encoding: [] + trailer: {} + host: graphql.us.jupiterone.io + remote_addr: "" + request_uri: "" + body: '{"query":"\nmutation CreateComplianceLibraryItem ($input: CreateComplianceLibraryItemInput!) {\n\tcreateComplianceLibraryItem(input: $input) {\n\t\tid\n\t}\n}\n","variables":{"input":{"name":"tf-acc-test-control","description":"","displayCategory":"","ref":"","webLink":""}},"operationName":"CreateComplianceLibraryItem"}' + form: {} + headers: + Cache-Control: + - no-cache + Content-Type: + - application/json + url: https://graphql.us.jupiterone.io/ + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 87 + uncompressed: false + body: | + {"data":{"createComplianceLibraryItem":{"id":"a4f10947-b942-4c9a-9e47-b9beae67dac3"}}} + headers: + Access-Control-Allow-Credentials: + - "true" + Content-Length: + - "87" + Content-Security-Policy: + - 'default-src ''self'';base-uri ''self'';block-all-mixed-content;font-src ''self'' https: data:;form-action ''self'';frame-ancestors ''self'';img-src ''self'' data:;object-src ''none'';script-src ''self'';script-src-attr ''none'';style-src ''self'' https: ''unsafe-inline'';upgrade-insecure-requests' + Content-Type: + - application/json + Cross-Origin-Embedder-Policy: + - require-corp + Cross-Origin-Opener-Policy: + - same-origin + Cross-Origin-Resource-Policy: + - same-origin + Expect-Ct: + - max-age=0 + Origin-Agent-Cluster: + - ?1 + Ratelimit-Limit: + - "1000" + Ratelimit-Remaining: + - "999" + Ratelimit-Requested: + - "1" + Ratelimit-Reset: + - "1" + Referrer-Policy: + - no-referrer + Strict-Transport-Security: + - max-age=15552000; includeSubDomains + Vary: + - Origin + X-Content-Type-Options: + - nosniff + X-Dns-Prefetch-Control: + - "off" + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Xss-Protection: + - "0" + status: 200 OK + code: 200 + duration: 1.455908875s + - id: 4 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 496 + transfer_encoding: [] + trailer: {} + host: graphql.us.jupiterone.io + remote_addr: "" + request_uri: "" + body: '{"query":"\nmutation AttachComplianceLibraryItemToComplianceFrameworkItem ($input: AttachComplianceLibraryItemToComplianceFrameworkItemInput!) {\n\tattachComplianceLibraryItemToComplianceFrameworkItem(input: $input) {\n\t\trelationshipType\n\t}\n}\n","variables":{"input":{"frameworkItemId":"58bf83f7-77bd-40d6-864a-34dc10dd5577","libraryItemId":"a4f10947-b942-4c9a-9e47-b9beae67dac3","relationshipType":"INHERIT_EVIDENCE"}},"operationName":"AttachComplianceLibraryItemToComplianceFrameworkItem"}' + form: {} + headers: + Cache-Control: + - no-cache + Content-Type: + - application/json + url: https://graphql.us.jupiterone.io/ + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 106 + uncompressed: false + body: | + {"data":{"attachComplianceLibraryItemToComplianceFrameworkItem":{"relationshipType":"INHERIT_EVIDENCE"}}} + headers: + Access-Control-Allow-Credentials: + - "true" + Content-Length: + - "106" + Content-Security-Policy: + - 'default-src ''self'';base-uri ''self'';block-all-mixed-content;font-src ''self'' https: data:;form-action ''self'';frame-ancestors ''self'';img-src ''self'' data:;object-src ''none'';script-src ''self'';script-src-attr ''none'';style-src ''self'' https: ''unsafe-inline'';upgrade-insecure-requests' + Content-Type: + - application/json + Cross-Origin-Embedder-Policy: + - require-corp + Cross-Origin-Opener-Policy: + - same-origin + Cross-Origin-Resource-Policy: + - same-origin + Expect-Ct: + - max-age=0 + Origin-Agent-Cluster: + - ?1 + Ratelimit-Limit: + - "1000" + Ratelimit-Remaining: + - "999" + Ratelimit-Requested: + - "1" + Ratelimit-Reset: + - "1" + Referrer-Policy: + - no-referrer + Strict-Transport-Security: + - max-age=15552000; includeSubDomains + Vary: + - Origin + X-Content-Type-Options: + - nosniff + X-Dns-Prefetch-Control: + - "off" + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Xss-Protection: + - "0" + status: 200 OK + code: 200 + duration: 493.763625ms + - id: 5 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 397 + transfer_encoding: [] + trailer: {} + host: graphql.us.jupiterone.io + remote_addr: "" + request_uri: "" + body: '{"query":"\nquery GetComplianceFrameworkItemRelationshipsById ($id: ID!) {\n\tcomplianceFrameworkItem(input: {id:$id}) {\n\t\tlibraryItems {\n\t\t\tinheritedEvidenceLibraryItems {\n\t\t\t\tid\n\t\t\t}\n\t\t\tignoredEvidenceLibraryItems {\n\t\t\t\tid\n\t\t\t}\n\t\t}\n\t}\n}\n","variables":{"id":"58bf83f7-77bd-40d6-864a-34dc10dd5577"},"operationName":"GetComplianceFrameworkItemRelationshipsById"}' + form: {} + headers: + Cache-Control: + - no-cache + Content-Type: + - application/json + url: https://graphql.us.jupiterone.io/ + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 169 + uncompressed: false + body: | + {"data":{"complianceFrameworkItem":{"libraryItems":{"inheritedEvidenceLibraryItems":[{"id":"a4f10947-b942-4c9a-9e47-b9beae67dac3"}],"ignoredEvidenceLibraryItems":[]}}}} + headers: + Access-Control-Allow-Credentials: + - "true" + Content-Length: + - "169" + Content-Security-Policy: + - 'default-src ''self'';base-uri ''self'';block-all-mixed-content;font-src ''self'' https: data:;form-action ''self'';frame-ancestors ''self'';img-src ''self'' data:;object-src ''none'';script-src ''self'';script-src-attr ''none'';style-src ''self'' https: ''unsafe-inline'';upgrade-insecure-requests' + Content-Type: + - application/json + Cross-Origin-Embedder-Policy: + - require-corp + Cross-Origin-Opener-Policy: + - same-origin + Cross-Origin-Resource-Policy: + - same-origin + Expect-Ct: + - max-age=0 + Origin-Agent-Cluster: + - ?1 + Ratelimit-Limit: + - "1000" + Ratelimit-Remaining: + - "999" + Ratelimit-Requested: + - "1" + Ratelimit-Reset: + - "1" + Referrer-Policy: + - no-referrer + Strict-Transport-Security: + - max-age=15552000; includeSubDomains + Vary: + - Origin + X-Content-Type-Options: + - nosniff + X-Dns-Prefetch-Control: + - "off" + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Xss-Protection: + - "0" + status: 200 OK + code: 200 + duration: 1.040642959s + - id: 6 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 397 + transfer_encoding: [] + trailer: {} + host: graphql.us.jupiterone.io + remote_addr: "" + request_uri: "" + body: '{"query":"\nquery GetComplianceFrameworkItemRelationshipsById ($id: ID!) {\n\tcomplianceFrameworkItem(input: {id:$id}) {\n\t\tlibraryItems {\n\t\t\tinheritedEvidenceLibraryItems {\n\t\t\t\tid\n\t\t\t}\n\t\t\tignoredEvidenceLibraryItems {\n\t\t\t\tid\n\t\t\t}\n\t\t}\n\t}\n}\n","variables":{"id":"58bf83f7-77bd-40d6-864a-34dc10dd5577"},"operationName":"GetComplianceFrameworkItemRelationshipsById"}' + form: {} + headers: + Cache-Control: + - no-cache + Content-Type: + - application/json + url: https://graphql.us.jupiterone.io/ + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 169 + uncompressed: false + body: | + {"data":{"complianceFrameworkItem":{"libraryItems":{"inheritedEvidenceLibraryItems":[{"id":"a4f10947-b942-4c9a-9e47-b9beae67dac3"}],"ignoredEvidenceLibraryItems":[]}}}} + headers: + Access-Control-Allow-Credentials: + - "true" + Content-Length: + - "169" + Content-Security-Policy: + - 'default-src ''self'';base-uri ''self'';block-all-mixed-content;font-src ''self'' https: data:;form-action ''self'';frame-ancestors ''self'';img-src ''self'' data:;object-src ''none'';script-src ''self'';script-src-attr ''none'';style-src ''self'' https: ''unsafe-inline'';upgrade-insecure-requests' + Content-Type: + - application/json + Cross-Origin-Embedder-Policy: + - require-corp + Cross-Origin-Opener-Policy: + - same-origin + Cross-Origin-Resource-Policy: + - same-origin + Expect-Ct: + - max-age=0 + Origin-Agent-Cluster: + - ?1 + Ratelimit-Limit: + - "1000" + Ratelimit-Remaining: + - "999" + Ratelimit-Requested: + - "1" + Ratelimit-Reset: + - "1" + Referrer-Policy: + - no-referrer + Strict-Transport-Security: + - max-age=15552000; includeSubDomains + Vary: + - Origin + X-Content-Type-Options: + - nosniff + X-Dns-Prefetch-Control: + - "off" + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Xss-Protection: + - "0" + status: 200 OK + code: 200 + duration: 1.140330208s + - id: 7 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 555 + transfer_encoding: [] + trailer: {} + host: graphql.us.jupiterone.io + remote_addr: "" + request_uri: "" + body: '{"query":"\nmutation UpdateComplianceLibraryItemToComplianceFrameworkItemRelationship ($input: UpdateComplianceLibraryItemToComplianceFrameworkItemRelationshipInput!) {\n\tupdateComplianceLibraryItemToComplianceFrameworkItemRelationship(input: $input) {\n\t\trelationshipType\n\t}\n}\n","variables":{"input":{"frameworkItemId":"58bf83f7-77bd-40d6-864a-34dc10dd5577","libraryItemId":"a4f10947-b942-4c9a-9e47-b9beae67dac3","updates":{"relationshipType":"IGNORE_EVIDENCE"}}},"operationName":"UpdateComplianceLibraryItemToComplianceFrameworkItemRelationship"}' + form: {} + headers: + Cache-Control: + - no-cache + Content-Type: + - application/json + url: https://graphql.us.jupiterone.io/ + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 117 + uncompressed: false + body: | + {"data":{"updateComplianceLibraryItemToComplianceFrameworkItemRelationship":{"relationshipType":"IGNORE_EVIDENCE"}}} + headers: + Access-Control-Allow-Credentials: + - "true" + Content-Length: + - "117" + Content-Security-Policy: + - 'default-src ''self'';base-uri ''self'';block-all-mixed-content;font-src ''self'' https: data:;form-action ''self'';frame-ancestors ''self'';img-src ''self'' data:;object-src ''none'';script-src ''self'';script-src-attr ''none'';style-src ''self'' https: ''unsafe-inline'';upgrade-insecure-requests' + Content-Type: + - application/json + Cross-Origin-Embedder-Policy: + - require-corp + Cross-Origin-Opener-Policy: + - same-origin + Cross-Origin-Resource-Policy: + - same-origin + Expect-Ct: + - max-age=0 + Origin-Agent-Cluster: + - ?1 + Ratelimit-Limit: + - "1000" + Ratelimit-Remaining: + - "999" + Ratelimit-Requested: + - "1" + Ratelimit-Reset: + - "1" + Referrer-Policy: + - no-referrer + Strict-Transport-Security: + - max-age=15552000; includeSubDomains + Vary: + - Origin + X-Content-Type-Options: + - nosniff + X-Dns-Prefetch-Control: + - "off" + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Xss-Protection: + - "0" + status: 200 OK + code: 200 + duration: 1.195835792s + - id: 8 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 397 + transfer_encoding: [] + trailer: {} + host: graphql.us.jupiterone.io + remote_addr: "" + request_uri: "" + body: '{"query":"\nquery GetComplianceFrameworkItemRelationshipsById ($id: ID!) {\n\tcomplianceFrameworkItem(input: {id:$id}) {\n\t\tlibraryItems {\n\t\t\tinheritedEvidenceLibraryItems {\n\t\t\t\tid\n\t\t\t}\n\t\t\tignoredEvidenceLibraryItems {\n\t\t\t\tid\n\t\t\t}\n\t\t}\n\t}\n}\n","variables":{"id":"58bf83f7-77bd-40d6-864a-34dc10dd5577"},"operationName":"GetComplianceFrameworkItemRelationshipsById"}' + form: {} + headers: + Cache-Control: + - no-cache + Content-Type: + - application/json + url: https://graphql.us.jupiterone.io/ + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 169 + uncompressed: false + body: | + {"data":{"complianceFrameworkItem":{"libraryItems":{"inheritedEvidenceLibraryItems":[],"ignoredEvidenceLibraryItems":[{"id":"a4f10947-b942-4c9a-9e47-b9beae67dac3"}]}}}} + headers: + Access-Control-Allow-Credentials: + - "true" + Content-Length: + - "169" + Content-Security-Policy: + - 'default-src ''self'';base-uri ''self'';block-all-mixed-content;font-src ''self'' https: data:;form-action ''self'';frame-ancestors ''self'';img-src ''self'' data:;object-src ''none'';script-src ''self'';script-src-attr ''none'';style-src ''self'' https: ''unsafe-inline'';upgrade-insecure-requests' + Content-Type: + - application/json + Cross-Origin-Embedder-Policy: + - require-corp + Cross-Origin-Opener-Policy: + - same-origin + Cross-Origin-Resource-Policy: + - same-origin + Expect-Ct: + - max-age=0 + Origin-Agent-Cluster: + - ?1 + Ratelimit-Limit: + - "1000" + Ratelimit-Remaining: + - "999" + Ratelimit-Requested: + - "1" + Ratelimit-Reset: + - "1" + Referrer-Policy: + - no-referrer + Strict-Transport-Security: + - max-age=15552000; includeSubDomains + Vary: + - Origin + X-Content-Type-Options: + - nosniff + X-Dns-Prefetch-Control: + - "off" + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Xss-Protection: + - "0" + status: 200 OK + code: 200 + duration: 963.460667ms + - id: 9 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 466 + transfer_encoding: [] + trailer: {} + host: graphql.us.jupiterone.io + remote_addr: "" + request_uri: "" + body: '{"query":"\nmutation DetachComplianceLibraryItemFromComplianceFrameworkItem ($input: DetachComplianceLibraryItemFromComplianceFrameworkItemInput!) {\n\tdetachComplianceLibraryItemFromComplianceFrameworkItem(input: $input) {\n\t\trelationshipType\n\t}\n}\n","variables":{"input":{"frameworkItemId":"58bf83f7-77bd-40d6-864a-34dc10dd5577","libraryItemId":"a4f10947-b942-4c9a-9e47-b9beae67dac3"}},"operationName":"DetachComplianceLibraryItemFromComplianceFrameworkItem"}' + form: {} + headers: + Cache-Control: + - no-cache + Content-Type: + - application/json + url: https://graphql.us.jupiterone.io/ + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 107 + uncompressed: false + body: | + {"data":{"detachComplianceLibraryItemFromComplianceFrameworkItem":{"relationshipType":"IGNORE_EVIDENCE"}}} + headers: + Access-Control-Allow-Credentials: + - "true" + Content-Length: + - "107" + Content-Security-Policy: + - 'default-src ''self'';base-uri ''self'';block-all-mixed-content;font-src ''self'' https: data:;form-action ''self'';frame-ancestors ''self'';img-src ''self'' data:;object-src ''none'';script-src ''self'';script-src-attr ''none'';style-src ''self'' https: ''unsafe-inline'';upgrade-insecure-requests' + Content-Type: + - application/json + Cross-Origin-Embedder-Policy: + - require-corp + Cross-Origin-Opener-Policy: + - same-origin + Cross-Origin-Resource-Policy: + - same-origin + Expect-Ct: + - max-age=0 + Origin-Agent-Cluster: + - ?1 + Ratelimit-Limit: + - "1000" + Ratelimit-Remaining: + - "999" + Ratelimit-Requested: + - "1" + Ratelimit-Reset: + - "1" + Referrer-Policy: + - no-referrer + Strict-Transport-Security: + - max-age=15552000; includeSubDomains + Vary: + - Origin + X-Content-Type-Options: + - nosniff + X-Dns-Prefetch-Control: + - "off" + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Xss-Protection: + - "0" + status: 200 OK + code: 200 + duration: 468.120375ms + - id: 10 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 253 + transfer_encoding: [] + trailer: {} + host: graphql.us.jupiterone.io + remote_addr: "" + request_uri: "" + body: '{"query":"\nmutation DeleteComplianceFramework ($input: DeleteComplianceFrameworkInput!) {\n\tdeleteComplianceFramework(input: $input)\n}\n","variables":{"input":{"id":"9e8595a7-6b6e-42cc-8a29-c80e85f9e899"}},"operationName":"DeleteComplianceFramework"}' + form: {} + headers: + Cache-Control: + - no-cache + Content-Type: + - application/json + url: https://graphql.us.jupiterone.io/ + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 78 + uncompressed: false + body: | + {"data":{"deleteComplianceFramework":"9e8595a7-6b6e-42cc-8a29-c80e85f9e899"}} + headers: + Access-Control-Allow-Credentials: + - "true" + Content-Length: + - "78" + Content-Security-Policy: + - 'default-src ''self'';base-uri ''self'';block-all-mixed-content;font-src ''self'' https: data:;form-action ''self'';frame-ancestors ''self'';img-src ''self'' data:;object-src ''none'';script-src ''self'';script-src-attr ''none'';style-src ''self'' https: ''unsafe-inline'';upgrade-insecure-requests' + Content-Type: + - application/json + Cross-Origin-Embedder-Policy: + - require-corp + Cross-Origin-Opener-Policy: + - same-origin + Cross-Origin-Resource-Policy: + - same-origin + Expect-Ct: + - max-age=0 + Origin-Agent-Cluster: + - ?1 + Ratelimit-Limit: + - "1000" + Ratelimit-Remaining: + - "999" + Ratelimit-Requested: + - "1" + Ratelimit-Reset: + - "1" + Referrer-Policy: + - no-referrer + Strict-Transport-Security: + - max-age=15552000; includeSubDomains + Vary: + - Origin + X-Content-Type-Options: + - nosniff + X-Dns-Prefetch-Control: + - "off" + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Xss-Protection: + - "0" + status: 200 OK + code: 200 + duration: 1.099630833s + - id: 11 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 220 + transfer_encoding: [] + trailer: {} + host: graphql.us.jupiterone.io + remote_addr: "" + request_uri: "" + body: '{"query":"\nmutation DeleteComplianceLibraryItem ($id: ID!) {\n\tdeleteComplianceLibraryItem(input: {id:$id})\n}\n","variables":{"id":"a4f10947-b942-4c9a-9e47-b9beae67dac3"},"operationName":"DeleteComplianceLibraryItem"}' + form: {} + headers: + Cache-Control: + - no-cache + Content-Type: + - application/json + url: https://graphql.us.jupiterone.io/ + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 80 + uncompressed: false + body: | + {"data":{"deleteComplianceLibraryItem":"a4f10947-b942-4c9a-9e47-b9beae67dac3"}} + headers: + Access-Control-Allow-Credentials: + - "true" + Content-Length: + - "80" + Content-Security-Policy: + - 'default-src ''self'';base-uri ''self'';block-all-mixed-content;font-src ''self'' https: data:;form-action ''self'';frame-ancestors ''self'';img-src ''self'' data:;object-src ''none'';script-src ''self'';script-src-attr ''none'';style-src ''self'' https: ''unsafe-inline'';upgrade-insecure-requests' + Content-Type: + - application/json + Cross-Origin-Embedder-Policy: + - require-corp + Cross-Origin-Opener-Policy: + - same-origin + Cross-Origin-Resource-Policy: + - same-origin + Expect-Ct: + - max-age=0 + Origin-Agent-Cluster: + - ?1 + Ratelimit-Limit: + - "1000" + Ratelimit-Remaining: + - "999" + Ratelimit-Requested: + - "1" + Ratelimit-Reset: + - "1" + Referrer-Policy: + - no-referrer + Strict-Transport-Security: + - max-age=15552000; includeSubDomains + Vary: + - Origin + X-Content-Type-Options: + - nosniff + X-Dns-Prefetch-Control: + - "off" + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Xss-Protection: + - "0" + status: 200 OK + code: 200 + duration: 439.663ms diff --git a/jupiterone/internal/client/compliance.graphql b/jupiterone/internal/client/compliance.graphql index ef45187b..c35088d2 100644 --- a/jupiterone/internal/client/compliance.graphql +++ b/jupiterone/internal/client/compliance.graphql @@ -129,3 +129,43 @@ mutation UpdateComplianceLibraryItem( id } } + +mutation AttachComplianceLibraryItemToComplianceFrameworkItem( + $input: AttachComplianceLibraryItemToComplianceFrameworkItemInput! +) { + attachComplianceLibraryItemToComplianceFrameworkItem(input: $input) { + relationshipType + } +} + +mutation UpdateComplianceLibraryItemToComplianceFrameworkItemRelationship( + $input: UpdateComplianceLibraryItemToComplianceFrameworkItemRelationshipInput! +) { + updateComplianceLibraryItemToComplianceFrameworkItemRelationship( + input: $input + ) { + relationshipType + } +} + +mutation DetachComplianceLibraryItemFromComplianceFrameworkItem( + $input: DetachComplianceLibraryItemFromComplianceFrameworkItemInput! +) { + detachComplianceLibraryItemFromComplianceFrameworkItem(input: $input) { + relationshipType + } +} + +# this query for for use in compliance_relationship resource reads +query GetComplianceFrameworkItemRelationshipsById($id: ID!) { + complianceFrameworkItem(input: { id: $id }) { + libraryItems { + inheritedEvidenceLibraryItems { + id + } + ignoredEvidenceLibraryItems { + id + } + } + } +} diff --git a/jupiterone/internal/client/generated.go b/jupiterone/internal/client/generated.go index fbc510f2..e1976658 100644 --- a/jupiterone/internal/client/generated.go +++ b/jupiterone/internal/client/generated.go @@ -8,6 +8,47 @@ import ( "github.com/Khan/genqlient/graphql" ) +// AttachComplianceLibraryItemToComplianceFrameworkItemAttachComplianceLibraryItemToComplianceFrameworkItemComplianceLibraryItemToComplianceFrameworkItemRelationship includes the requested fields of the GraphQL type ComplianceLibraryItemToComplianceFrameworkItemRelationship. +type AttachComplianceLibraryItemToComplianceFrameworkItemAttachComplianceLibraryItemToComplianceFrameworkItemComplianceLibraryItemToComplianceFrameworkItemRelationship struct { + RelationshipType LibraryItemToFrameworkItemRelationshipType `json:"relationshipType"` +} + +// GetRelationshipType returns AttachComplianceLibraryItemToComplianceFrameworkItemAttachComplianceLibraryItemToComplianceFrameworkItemComplianceLibraryItemToComplianceFrameworkItemRelationship.RelationshipType, and is useful for accessing the field via an interface. +func (v *AttachComplianceLibraryItemToComplianceFrameworkItemAttachComplianceLibraryItemToComplianceFrameworkItemComplianceLibraryItemToComplianceFrameworkItemRelationship) GetRelationshipType() LibraryItemToFrameworkItemRelationshipType { + return v.RelationshipType +} + +type AttachComplianceLibraryItemToComplianceFrameworkItemInput struct { + FrameworkItemId string `json:"frameworkItemId"` + LibraryItemId string `json:"libraryItemId"` + RelationshipType LibraryItemToFrameworkItemRelationshipType `json:"relationshipType"` +} + +// GetFrameworkItemId returns AttachComplianceLibraryItemToComplianceFrameworkItemInput.FrameworkItemId, and is useful for accessing the field via an interface. +func (v *AttachComplianceLibraryItemToComplianceFrameworkItemInput) GetFrameworkItemId() string { + return v.FrameworkItemId +} + +// GetLibraryItemId returns AttachComplianceLibraryItemToComplianceFrameworkItemInput.LibraryItemId, and is useful for accessing the field via an interface. +func (v *AttachComplianceLibraryItemToComplianceFrameworkItemInput) GetLibraryItemId() string { + return v.LibraryItemId +} + +// GetRelationshipType returns AttachComplianceLibraryItemToComplianceFrameworkItemInput.RelationshipType, and is useful for accessing the field via an interface. +func (v *AttachComplianceLibraryItemToComplianceFrameworkItemInput) GetRelationshipType() LibraryItemToFrameworkItemRelationshipType { + return v.RelationshipType +} + +// AttachComplianceLibraryItemToComplianceFrameworkItemResponse is returned by AttachComplianceLibraryItemToComplianceFrameworkItem on success. +type AttachComplianceLibraryItemToComplianceFrameworkItemResponse struct { + AttachComplianceLibraryItemToComplianceFrameworkItem AttachComplianceLibraryItemToComplianceFrameworkItemAttachComplianceLibraryItemToComplianceFrameworkItemComplianceLibraryItemToComplianceFrameworkItemRelationship `json:"attachComplianceLibraryItemToComplianceFrameworkItem"` +} + +// GetAttachComplianceLibraryItemToComplianceFrameworkItem returns AttachComplianceLibraryItemToComplianceFrameworkItemResponse.AttachComplianceLibraryItemToComplianceFrameworkItem, and is useful for accessing the field via an interface. +func (v *AttachComplianceLibraryItemToComplianceFrameworkItemResponse) GetAttachComplianceLibraryItemToComplianceFrameworkItem() AttachComplianceLibraryItemToComplianceFrameworkItemAttachComplianceLibraryItemToComplianceFrameworkItemComplianceLibraryItemToComplianceFrameworkItemRelationship { + return v.AttachComplianceLibraryItemToComplianceFrameworkItem +} + type ComplianceFrameworkItemAuditStatus string const ( @@ -635,6 +676,41 @@ func (v *DeleteRuleInstanceResponse) GetDeleteRuleInstance() DeleteRuleInstanceD return v.DeleteRuleInstance } +// DetachComplianceLibraryItemFromComplianceFrameworkItemDetachComplianceLibraryItemFromComplianceFrameworkItemComplianceLibraryItemToComplianceFrameworkItemRelationship includes the requested fields of the GraphQL type ComplianceLibraryItemToComplianceFrameworkItemRelationship. +type DetachComplianceLibraryItemFromComplianceFrameworkItemDetachComplianceLibraryItemFromComplianceFrameworkItemComplianceLibraryItemToComplianceFrameworkItemRelationship struct { + RelationshipType LibraryItemToFrameworkItemRelationshipType `json:"relationshipType"` +} + +// GetRelationshipType returns DetachComplianceLibraryItemFromComplianceFrameworkItemDetachComplianceLibraryItemFromComplianceFrameworkItemComplianceLibraryItemToComplianceFrameworkItemRelationship.RelationshipType, and is useful for accessing the field via an interface. +func (v *DetachComplianceLibraryItemFromComplianceFrameworkItemDetachComplianceLibraryItemFromComplianceFrameworkItemComplianceLibraryItemToComplianceFrameworkItemRelationship) GetRelationshipType() LibraryItemToFrameworkItemRelationshipType { + return v.RelationshipType +} + +type DetachComplianceLibraryItemFromComplianceFrameworkItemInput struct { + FrameworkItemId string `json:"frameworkItemId"` + LibraryItemId string `json:"libraryItemId"` +} + +// GetFrameworkItemId returns DetachComplianceLibraryItemFromComplianceFrameworkItemInput.FrameworkItemId, and is useful for accessing the field via an interface. +func (v *DetachComplianceLibraryItemFromComplianceFrameworkItemInput) GetFrameworkItemId() string { + return v.FrameworkItemId +} + +// GetLibraryItemId returns DetachComplianceLibraryItemFromComplianceFrameworkItemInput.LibraryItemId, and is useful for accessing the field via an interface. +func (v *DetachComplianceLibraryItemFromComplianceFrameworkItemInput) GetLibraryItemId() string { + return v.LibraryItemId +} + +// DetachComplianceLibraryItemFromComplianceFrameworkItemResponse is returned by DetachComplianceLibraryItemFromComplianceFrameworkItem on success. +type DetachComplianceLibraryItemFromComplianceFrameworkItemResponse struct { + DetachComplianceLibraryItemFromComplianceFrameworkItem DetachComplianceLibraryItemFromComplianceFrameworkItemDetachComplianceLibraryItemFromComplianceFrameworkItemComplianceLibraryItemToComplianceFrameworkItemRelationship `json:"detachComplianceLibraryItemFromComplianceFrameworkItem"` +} + +// GetDetachComplianceLibraryItemFromComplianceFrameworkItem returns DetachComplianceLibraryItemFromComplianceFrameworkItemResponse.DetachComplianceLibraryItemFromComplianceFrameworkItem, and is useful for accessing the field via an interface. +func (v *DetachComplianceLibraryItemFromComplianceFrameworkItemResponse) GetDetachComplianceLibraryItemFromComplianceFrameworkItem() DetachComplianceLibraryItemFromComplianceFrameworkItemDetachComplianceLibraryItemFromComplianceFrameworkItemComplianceLibraryItemToComplianceFrameworkItemRelationship { + return v.DetachComplianceLibraryItemFromComplianceFrameworkItem +} + // GetComplianceFrameworkByIdComplianceFramework includes the requested fields of the GraphQL type ComplianceFramework. type GetComplianceFrameworkByIdComplianceFramework struct { Id string `json:"id"` @@ -759,6 +835,62 @@ func (v *GetComplianceFrameworkItemByIdResponse) GetComplianceFrameworkItem() Ge return v.ComplianceFrameworkItem } +// GetComplianceFrameworkItemRelationshipsByIdComplianceFrameworkItem includes the requested fields of the GraphQL type ComplianceFrameworkItem. +type GetComplianceFrameworkItemRelationshipsByIdComplianceFrameworkItem struct { + LibraryItems GetComplianceFrameworkItemRelationshipsByIdComplianceFrameworkItemLibraryItemsComplianceLibraryItemsForFrameworkItem `json:"libraryItems"` +} + +// GetLibraryItems returns GetComplianceFrameworkItemRelationshipsByIdComplianceFrameworkItem.LibraryItems, and is useful for accessing the field via an interface. +func (v *GetComplianceFrameworkItemRelationshipsByIdComplianceFrameworkItem) GetLibraryItems() GetComplianceFrameworkItemRelationshipsByIdComplianceFrameworkItemLibraryItemsComplianceLibraryItemsForFrameworkItem { + return v.LibraryItems +} + +// GetComplianceFrameworkItemRelationshipsByIdComplianceFrameworkItemLibraryItemsComplianceLibraryItemsForFrameworkItem includes the requested fields of the GraphQL type ComplianceLibraryItemsForFrameworkItem. +type GetComplianceFrameworkItemRelationshipsByIdComplianceFrameworkItemLibraryItemsComplianceLibraryItemsForFrameworkItem struct { + InheritedEvidenceLibraryItems []GetComplianceFrameworkItemRelationshipsByIdComplianceFrameworkItemLibraryItemsComplianceLibraryItemsForFrameworkItemInheritedEvidenceLibraryItemsComplianceLibraryItem `json:"inheritedEvidenceLibraryItems"` + IgnoredEvidenceLibraryItems []GetComplianceFrameworkItemRelationshipsByIdComplianceFrameworkItemLibraryItemsComplianceLibraryItemsForFrameworkItemIgnoredEvidenceLibraryItemsComplianceLibraryItem `json:"ignoredEvidenceLibraryItems"` +} + +// GetInheritedEvidenceLibraryItems returns GetComplianceFrameworkItemRelationshipsByIdComplianceFrameworkItemLibraryItemsComplianceLibraryItemsForFrameworkItem.InheritedEvidenceLibraryItems, and is useful for accessing the field via an interface. +func (v *GetComplianceFrameworkItemRelationshipsByIdComplianceFrameworkItemLibraryItemsComplianceLibraryItemsForFrameworkItem) GetInheritedEvidenceLibraryItems() []GetComplianceFrameworkItemRelationshipsByIdComplianceFrameworkItemLibraryItemsComplianceLibraryItemsForFrameworkItemInheritedEvidenceLibraryItemsComplianceLibraryItem { + return v.InheritedEvidenceLibraryItems +} + +// GetIgnoredEvidenceLibraryItems returns GetComplianceFrameworkItemRelationshipsByIdComplianceFrameworkItemLibraryItemsComplianceLibraryItemsForFrameworkItem.IgnoredEvidenceLibraryItems, and is useful for accessing the field via an interface. +func (v *GetComplianceFrameworkItemRelationshipsByIdComplianceFrameworkItemLibraryItemsComplianceLibraryItemsForFrameworkItem) GetIgnoredEvidenceLibraryItems() []GetComplianceFrameworkItemRelationshipsByIdComplianceFrameworkItemLibraryItemsComplianceLibraryItemsForFrameworkItemIgnoredEvidenceLibraryItemsComplianceLibraryItem { + return v.IgnoredEvidenceLibraryItems +} + +// GetComplianceFrameworkItemRelationshipsByIdComplianceFrameworkItemLibraryItemsComplianceLibraryItemsForFrameworkItemIgnoredEvidenceLibraryItemsComplianceLibraryItem includes the requested fields of the GraphQL type ComplianceLibraryItem. +type GetComplianceFrameworkItemRelationshipsByIdComplianceFrameworkItemLibraryItemsComplianceLibraryItemsForFrameworkItemIgnoredEvidenceLibraryItemsComplianceLibraryItem struct { + Id string `json:"id"` +} + +// GetId returns GetComplianceFrameworkItemRelationshipsByIdComplianceFrameworkItemLibraryItemsComplianceLibraryItemsForFrameworkItemIgnoredEvidenceLibraryItemsComplianceLibraryItem.Id, and is useful for accessing the field via an interface. +func (v *GetComplianceFrameworkItemRelationshipsByIdComplianceFrameworkItemLibraryItemsComplianceLibraryItemsForFrameworkItemIgnoredEvidenceLibraryItemsComplianceLibraryItem) GetId() string { + return v.Id +} + +// GetComplianceFrameworkItemRelationshipsByIdComplianceFrameworkItemLibraryItemsComplianceLibraryItemsForFrameworkItemInheritedEvidenceLibraryItemsComplianceLibraryItem includes the requested fields of the GraphQL type ComplianceLibraryItem. +type GetComplianceFrameworkItemRelationshipsByIdComplianceFrameworkItemLibraryItemsComplianceLibraryItemsForFrameworkItemInheritedEvidenceLibraryItemsComplianceLibraryItem struct { + Id string `json:"id"` +} + +// GetId returns GetComplianceFrameworkItemRelationshipsByIdComplianceFrameworkItemLibraryItemsComplianceLibraryItemsForFrameworkItemInheritedEvidenceLibraryItemsComplianceLibraryItem.Id, and is useful for accessing the field via an interface. +func (v *GetComplianceFrameworkItemRelationshipsByIdComplianceFrameworkItemLibraryItemsComplianceLibraryItemsForFrameworkItemInheritedEvidenceLibraryItemsComplianceLibraryItem) GetId() string { + return v.Id +} + +// GetComplianceFrameworkItemRelationshipsByIdResponse is returned by GetComplianceFrameworkItemRelationshipsById on success. +type GetComplianceFrameworkItemRelationshipsByIdResponse struct { + ComplianceFrameworkItem GetComplianceFrameworkItemRelationshipsByIdComplianceFrameworkItem `json:"complianceFrameworkItem"` +} + +// GetComplianceFrameworkItem returns GetComplianceFrameworkItemRelationshipsByIdResponse.ComplianceFrameworkItem, and is useful for accessing the field via an interface. +func (v *GetComplianceFrameworkItemRelationshipsByIdResponse) GetComplianceFrameworkItem() GetComplianceFrameworkItemRelationshipsByIdComplianceFrameworkItem { + return v.ComplianceFrameworkItem +} + // GetComplianceGroupsComplianceFramework includes the requested fields of the GraphQL type ComplianceFramework. type GetComplianceGroupsComplianceFramework struct { Groups []ComplianceGroup `json:"groups"` @@ -1014,6 +1146,13 @@ func (v *J1QueryInput) GetVersion() string { return v.Version } // GetIncludeDeleted returns J1QueryInput.IncludeDeleted, and is useful for accessing the field via an interface. func (v *J1QueryInput) GetIncludeDeleted() bool { return v.IncludeDeleted } +type LibraryItemToFrameworkItemRelationshipType string + +const ( + LibraryItemToFrameworkItemRelationshipTypeIgnoreEvidence LibraryItemToFrameworkItemRelationshipType = "IGNORE_EVIDENCE" + LibraryItemToFrameworkItemRelationshipTypeInheritEvidence LibraryItemToFrameworkItemRelationshipType = "INHERIT_EVIDENCE" +) + type QueryResultsAre string const ( @@ -1423,6 +1562,56 @@ func (v *UpdateComplianceLibraryItemResponse) GetUpdateComplianceLibraryItem() U return v.UpdateComplianceLibraryItem } +type UpdateComplianceLibraryItemToComplianceFrameworkItemRelationshipFields struct { + RelationshipType LibraryItemToFrameworkItemRelationshipType `json:"relationshipType"` +} + +// GetRelationshipType returns UpdateComplianceLibraryItemToComplianceFrameworkItemRelationshipFields.RelationshipType, and is useful for accessing the field via an interface. +func (v *UpdateComplianceLibraryItemToComplianceFrameworkItemRelationshipFields) GetRelationshipType() LibraryItemToFrameworkItemRelationshipType { + return v.RelationshipType +} + +type UpdateComplianceLibraryItemToComplianceFrameworkItemRelationshipInput struct { + FrameworkItemId string `json:"frameworkItemId"` + LibraryItemId string `json:"libraryItemId"` + Updates UpdateComplianceLibraryItemToComplianceFrameworkItemRelationshipFields `json:"updates"` +} + +// GetFrameworkItemId returns UpdateComplianceLibraryItemToComplianceFrameworkItemRelationshipInput.FrameworkItemId, and is useful for accessing the field via an interface. +func (v *UpdateComplianceLibraryItemToComplianceFrameworkItemRelationshipInput) GetFrameworkItemId() string { + return v.FrameworkItemId +} + +// GetLibraryItemId returns UpdateComplianceLibraryItemToComplianceFrameworkItemRelationshipInput.LibraryItemId, and is useful for accessing the field via an interface. +func (v *UpdateComplianceLibraryItemToComplianceFrameworkItemRelationshipInput) GetLibraryItemId() string { + return v.LibraryItemId +} + +// GetUpdates returns UpdateComplianceLibraryItemToComplianceFrameworkItemRelationshipInput.Updates, and is useful for accessing the field via an interface. +func (v *UpdateComplianceLibraryItemToComplianceFrameworkItemRelationshipInput) GetUpdates() UpdateComplianceLibraryItemToComplianceFrameworkItemRelationshipFields { + return v.Updates +} + +// UpdateComplianceLibraryItemToComplianceFrameworkItemRelationshipResponse is returned by UpdateComplianceLibraryItemToComplianceFrameworkItemRelationship on success. +type UpdateComplianceLibraryItemToComplianceFrameworkItemRelationshipResponse struct { + UpdateComplianceLibraryItemToComplianceFrameworkItemRelationship UpdateComplianceLibraryItemToComplianceFrameworkItemRelationshipUpdateComplianceLibraryItemToComplianceFrameworkItemRelationship `json:"updateComplianceLibraryItemToComplianceFrameworkItemRelationship"` +} + +// GetUpdateComplianceLibraryItemToComplianceFrameworkItemRelationship returns UpdateComplianceLibraryItemToComplianceFrameworkItemRelationshipResponse.UpdateComplianceLibraryItemToComplianceFrameworkItemRelationship, and is useful for accessing the field via an interface. +func (v *UpdateComplianceLibraryItemToComplianceFrameworkItemRelationshipResponse) GetUpdateComplianceLibraryItemToComplianceFrameworkItemRelationship() UpdateComplianceLibraryItemToComplianceFrameworkItemRelationshipUpdateComplianceLibraryItemToComplianceFrameworkItemRelationship { + return v.UpdateComplianceLibraryItemToComplianceFrameworkItemRelationship +} + +// UpdateComplianceLibraryItemToComplianceFrameworkItemRelationshipUpdateComplianceLibraryItemToComplianceFrameworkItemRelationship includes the requested fields of the GraphQL type ComplianceLibraryItemToComplianceFrameworkItemRelationship. +type UpdateComplianceLibraryItemToComplianceFrameworkItemRelationshipUpdateComplianceLibraryItemToComplianceFrameworkItemRelationship struct { + RelationshipType LibraryItemToFrameworkItemRelationshipType `json:"relationshipType"` +} + +// GetRelationshipType returns UpdateComplianceLibraryItemToComplianceFrameworkItemRelationshipUpdateComplianceLibraryItemToComplianceFrameworkItemRelationship.RelationshipType, and is useful for accessing the field via an interface. +func (v *UpdateComplianceLibraryItemToComplianceFrameworkItemRelationshipUpdateComplianceLibraryItemToComplianceFrameworkItemRelationship) GetRelationshipType() LibraryItemToFrameworkItemRelationshipType { + return v.RelationshipType +} + // UpdateComplianceLibraryItemUpdateComplianceLibraryItem includes the requested fields of the GraphQL type ComplianceLibraryItem. type UpdateComplianceLibraryItemUpdateComplianceLibraryItem struct { Id string `json:"id"` @@ -1671,6 +1860,16 @@ func (v *UpdateReferencedQuestionRuleInstanceUpdateReferencedQuestionRuleInstanc return v.Operations } +// __AttachComplianceLibraryItemToComplianceFrameworkItemInput is used internally by genqlient +type __AttachComplianceLibraryItemToComplianceFrameworkItemInput struct { + Input AttachComplianceLibraryItemToComplianceFrameworkItemInput `json:"input"` +} + +// GetInput returns __AttachComplianceLibraryItemToComplianceFrameworkItemInput.Input, and is useful for accessing the field via an interface. +func (v *__AttachComplianceLibraryItemToComplianceFrameworkItemInput) GetInput() AttachComplianceLibraryItemToComplianceFrameworkItemInput { + return v.Input +} + // __CreateComplianceFrameworkInput is used internally by genqlient type __CreateComplianceFrameworkInput struct { Framework CreateComplianceFrameworkInput `json:"framework"` @@ -1785,6 +1984,16 @@ type __DeleteRuleInstanceInput struct { // GetId returns __DeleteRuleInstanceInput.Id, and is useful for accessing the field via an interface. func (v *__DeleteRuleInstanceInput) GetId() string { return v.Id } +// __DetachComplianceLibraryItemFromComplianceFrameworkItemInput is used internally by genqlient +type __DetachComplianceLibraryItemFromComplianceFrameworkItemInput struct { + Input DetachComplianceLibraryItemFromComplianceFrameworkItemInput `json:"input"` +} + +// GetInput returns __DetachComplianceLibraryItemFromComplianceFrameworkItemInput.Input, and is useful for accessing the field via an interface. +func (v *__DetachComplianceLibraryItemFromComplianceFrameworkItemInput) GetInput() DetachComplianceLibraryItemFromComplianceFrameworkItemInput { + return v.Input +} + // __GetComplianceFrameworkByIdInput is used internally by genqlient type __GetComplianceFrameworkByIdInput struct { FrameworkId string `json:"frameworkId"` @@ -1801,6 +2010,14 @@ type __GetComplianceFrameworkItemByIdInput struct { // GetId returns __GetComplianceFrameworkItemByIdInput.Id, and is useful for accessing the field via an interface. func (v *__GetComplianceFrameworkItemByIdInput) GetId() string { return v.Id } +// __GetComplianceFrameworkItemRelationshipsByIdInput is used internally by genqlient +type __GetComplianceFrameworkItemRelationshipsByIdInput struct { + Id string `json:"id"` +} + +// GetId returns __GetComplianceFrameworkItemRelationshipsByIdInput.Id, and is useful for accessing the field via an interface. +func (v *__GetComplianceFrameworkItemRelationshipsByIdInput) GetId() string { return v.Id } + // __GetComplianceGroupsInput is used internally by genqlient type __GetComplianceGroupsInput struct { FrameworkId string `json:"frameworkId"` @@ -1869,6 +2086,16 @@ func (v *__UpdateComplianceLibraryItemInput) GetInput() UpdateComplianceLibraryI return v.Input } +// __UpdateComplianceLibraryItemToComplianceFrameworkItemRelationshipInput is used internally by genqlient +type __UpdateComplianceLibraryItemToComplianceFrameworkItemRelationshipInput struct { + Input UpdateComplianceLibraryItemToComplianceFrameworkItemRelationshipInput `json:"input"` +} + +// GetInput returns __UpdateComplianceLibraryItemToComplianceFrameworkItemRelationshipInput.Input, and is useful for accessing the field via an interface. +func (v *__UpdateComplianceLibraryItemToComplianceFrameworkItemRelationshipInput) GetInput() UpdateComplianceLibraryItemToComplianceFrameworkItemRelationshipInput { + return v.Input +} + // __UpdateInlineQuestionRuleInstanceInput is used internally by genqlient type __UpdateInlineQuestionRuleInstanceInput struct { Instance UpdateInlineQuestionRuleInstanceInput `json:"instance"` @@ -1901,6 +2128,38 @@ func (v *__UpdateReferencedQuestionRuleInstanceInput) GetInstance() UpdateRefere return v.Instance } +func AttachComplianceLibraryItemToComplianceFrameworkItem( + ctx context.Context, + client graphql.Client, + input AttachComplianceLibraryItemToComplianceFrameworkItemInput, +) (*AttachComplianceLibraryItemToComplianceFrameworkItemResponse, error) { + req := &graphql.Request{ + OpName: "AttachComplianceLibraryItemToComplianceFrameworkItem", + Query: ` +mutation AttachComplianceLibraryItemToComplianceFrameworkItem ($input: AttachComplianceLibraryItemToComplianceFrameworkItemInput!) { + attachComplianceLibraryItemToComplianceFrameworkItem(input: $input) { + relationshipType + } +} +`, + Variables: &__AttachComplianceLibraryItemToComplianceFrameworkItemInput{ + Input: input, + }, + } + var err error + + var data AttachComplianceLibraryItemToComplianceFrameworkItemResponse + resp := &graphql.Response{Data: &data} + + err = client.MakeRequest( + ctx, + req, + resp, + ) + + return &data, err +} + func CreateComplianceFramework( ctx context.Context, client graphql.Client, @@ -2329,6 +2588,38 @@ mutation DeleteRuleInstance ($id: ID!) { return &data, err } +func DetachComplianceLibraryItemFromComplianceFrameworkItem( + ctx context.Context, + client graphql.Client, + input DetachComplianceLibraryItemFromComplianceFrameworkItemInput, +) (*DetachComplianceLibraryItemFromComplianceFrameworkItemResponse, error) { + req := &graphql.Request{ + OpName: "DetachComplianceLibraryItemFromComplianceFrameworkItem", + Query: ` +mutation DetachComplianceLibraryItemFromComplianceFrameworkItem ($input: DetachComplianceLibraryItemFromComplianceFrameworkItemInput!) { + detachComplianceLibraryItemFromComplianceFrameworkItem(input: $input) { + relationshipType + } +} +`, + Variables: &__DetachComplianceLibraryItemFromComplianceFrameworkItemInput{ + Input: input, + }, + } + var err error + + var data DetachComplianceLibraryItemFromComplianceFrameworkItemResponse + resp := &graphql.Response{Data: &data} + + err = client.MakeRequest( + ctx, + req, + resp, + ) + + return &data, err +} + func GetComplianceFrameworkById( ctx context.Context, client graphql.Client, @@ -2410,6 +2701,46 @@ query GetComplianceFrameworkItemById ($id: ID!) { return &data, err } +// this query for for use in compliance_relationship resource reads +func GetComplianceFrameworkItemRelationshipsById( + ctx context.Context, + client graphql.Client, + id string, +) (*GetComplianceFrameworkItemRelationshipsByIdResponse, error) { + req := &graphql.Request{ + OpName: "GetComplianceFrameworkItemRelationshipsById", + Query: ` +query GetComplianceFrameworkItemRelationshipsById ($id: ID!) { + complianceFrameworkItem(input: {id:$id}) { + libraryItems { + inheritedEvidenceLibraryItems { + id + } + ignoredEvidenceLibraryItems { + id + } + } + } +} +`, + Variables: &__GetComplianceFrameworkItemRelationshipsByIdInput{ + Id: id, + }, + } + var err error + + var data GetComplianceFrameworkItemRelationshipsByIdResponse + resp := &graphql.Response{Data: &data} + + err = client.MakeRequest( + ctx, + req, + resp, + ) + + return &data, err +} + // FIXME: there is currently no `complianceGroup` query, so the full list // must be retrieved and then searched for the matching ID func GetComplianceGroups( @@ -2722,6 +3053,38 @@ mutation UpdateComplianceLibraryItem ($input: UpdateComplianceLibraryItemInput!) return &data, err } +func UpdateComplianceLibraryItemToComplianceFrameworkItemRelationship( + ctx context.Context, + client graphql.Client, + input UpdateComplianceLibraryItemToComplianceFrameworkItemRelationshipInput, +) (*UpdateComplianceLibraryItemToComplianceFrameworkItemRelationshipResponse, error) { + req := &graphql.Request{ + OpName: "UpdateComplianceLibraryItemToComplianceFrameworkItemRelationship", + Query: ` +mutation UpdateComplianceLibraryItemToComplianceFrameworkItemRelationship ($input: UpdateComplianceLibraryItemToComplianceFrameworkItemRelationshipInput!) { + updateComplianceLibraryItemToComplianceFrameworkItemRelationship(input: $input) { + relationshipType + } +} +`, + Variables: &__UpdateComplianceLibraryItemToComplianceFrameworkItemRelationshipInput{ + Input: input, + }, + } + var err error + + var data UpdateComplianceLibraryItemToComplianceFrameworkItemRelationshipResponse + resp := &graphql.Response{Data: &data} + + err = client.MakeRequest( + ctx, + req, + resp, + ) + + return &data, err +} + // The API is inconsistent about empty values, so `omitempty` is required // for some of these. For example "when: null," will produce an error, but // `templates: null` will not when include in the request. diff --git a/jupiterone/modifiers.go b/jupiterone/modifiers.go index 3254d95c..01c14925 100644 --- a/jupiterone/modifiers.go +++ b/jupiterone/modifiers.go @@ -11,6 +11,9 @@ import ( "github.com/hashicorp/terraform-plugin-framework/types" ) +// UUIDStrLength is the length of UUID. TODO: Add a UUID validator +const UUIDStrLength = 36 + var _ planmodifier.String = (*jsonIgnoreDiff)(nil) var _ planmodifier.List = (*jsonIgnoreDiff)(nil) var _ planmodifier.Map = (*jsonIgnoreDiff)(nil) diff --git a/jupiterone/provider.go b/jupiterone/provider.go index bab1b309..7404b0f7 100644 --- a/jupiterone/provider.go +++ b/jupiterone/provider.go @@ -135,6 +135,7 @@ func (*JupiterOneProvider) Resources(context.Context) []func() resource.Resource NewGroupResource, NewFrameworkItemResource, NewLibraryItemResource, + NewComplianceRelationshipResource, } } diff --git a/jupiterone/resource_compliance_relationship.go b/jupiterone/resource_compliance_relationship.go new file mode 100644 index 00000000..11c0980a --- /dev/null +++ b/jupiterone/resource_compliance_relationship.go @@ -0,0 +1,233 @@ +package jupiterone + +import ( + "context" + "fmt" + + "github.com/Khan/genqlient/graphql" + "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/jupiterone/terraform-provider-jupiterone/jupiterone/internal/client" +) + +var ComplianceRelationshipTypes = []string{ + string(client.LibraryItemToFrameworkItemRelationshipTypeIgnoreEvidence), + string(client.LibraryItemToFrameworkItemRelationshipTypeInheritEvidence), +} + +type ComplianceRelationshipModel struct { + Id types.String `tfsdk:"id"` + LibraryItemId types.String `tfsdk:"library_item_id"` + FrameworkItemId types.String `tfsdk:"framework_item_id"` + RelationshipType types.String `tfsdk:"relationship_type"` +} + +type ComplianceRelationshipResource struct { + version string + qlient graphql.Client +} + +var _ resource.Resource = &ComplianceRelationshipResource{} +var _ resource.ResourceWithConfigure = &ComplianceRelationshipResource{} + +func NewComplianceRelationshipResource() resource.Resource { + return &ComplianceRelationshipResource{} +} + +// Metadata implements resource.Resource. +func (*ComplianceRelationshipResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_compliance_relationship" +} + +func (r *ComplianceRelationshipResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { + // Prevent panic if the provider has not been configured. + if req.ProviderData == nil { + return + } + + p, ok := req.ProviderData.(*JupiterOneProvider) + + if !ok { + resp.Diagnostics.AddError( + "Unexpected Resource Configure Type", + fmt.Sprintf("Expected JupiterOneProvider, got: %T. Please report this issue to the provider developers.", req.ProviderData), + ) + + return + } + + r.version = p.version + r.qlient = p.Qlient +} + +func (*ComplianceRelationshipResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Description: "A relationship between a framework item (requirement) and a library item (control).", + Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ + Computed: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + }, + "library_item_id": schema.StringAttribute{ + Required: true, + Description: "The id of the library item (control) to link", + Validators: []validator.String{ + stringvalidator.LengthBetween(UUIDStrLength, UUIDStrLength), + }, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + }, + "framework_item_id": schema.StringAttribute{ + Required: true, + Description: "The id of the framework item (requirement) to link", + Validators: []validator.String{ + stringvalidator.LengthBetween(UUIDStrLength, UUIDStrLength), + }, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + }, + "relationship_type": schema.StringAttribute{ + Required: true, + Description: "Whether to INHERIT_EVIDENCE or IGNORE_EVIDENCE in the linked framework item", + Validators: []validator.String{ + stringvalidator.OneOf(ComplianceRelationshipTypes...), + }, + }, + }, + } +} + +// Create implements resource.Resource. +func (r *ComplianceRelationshipResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var data *ComplianceRelationshipModel + + // Read Terraform plan data into the model + resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) + + if resp.Diagnostics.HasError() { + return + } + + _, err := client.AttachComplianceLibraryItemToComplianceFrameworkItem(ctx, r.qlient, client.AttachComplianceLibraryItemToComplianceFrameworkItemInput{ + LibraryItemId: data.LibraryItemId.ValueString(), + FrameworkItemId: data.FrameworkItemId.ValueString(), + RelationshipType: client.LibraryItemToFrameworkItemRelationshipType(data.RelationshipType.ValueString()), + }) + + if err != nil { + resp.Diagnostics.AddError("failed to create compliance relationship", err.Error()) + return + } + + data.Id = types.StringValue(fmt.Sprintf("%s-%s", data.LibraryItemId.ValueString(), data.FrameworkItemId.ValueString())) + + tflog.Trace(ctx, "Attached compliance relationship", + map[string]interface{}{"library_item_id": data.LibraryItemId, "framework_item_id": data.FrameworkItemId}) + + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +// Delete implements resource.Resource. +func (r *ComplianceRelationshipResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + var data ComplianceRelationshipModel + + // Read Terraform ste into the model + resp.Diagnostics.Append(req.State.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + _, err := client.DetachComplianceLibraryItemFromComplianceFrameworkItem(ctx, r.qlient, client.DetachComplianceLibraryItemFromComplianceFrameworkItemInput{ + LibraryItemId: data.LibraryItemId.ValueString(), + FrameworkItemId: data.FrameworkItemId.ValueString(), + }) + + if err != nil { + resp.Diagnostics.AddError("failed to delete compliance relationship", err.Error()) + return + } + + data.Id = types.StringValue(fmt.Sprintf("%s-%s", data.LibraryItemId.ValueString(), data.FrameworkItemId.ValueString())) + + tflog.Trace(ctx, "Detached compliance relationship", + map[string]interface{}{"library_item_id": data.LibraryItemId, "framework_item_id": data.FrameworkItemId}) + + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +// Read implements resource.Resource. +func (r *ComplianceRelationshipResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var data ComplianceRelationshipModel + + // Read Terraform ste into the model + resp.Diagnostics.Append(req.State.Get(ctx, &data)...) + + if resp.Diagnostics.HasError() { + return + } + + var i client.GetComplianceFrameworkItemRelationshipsByIdComplianceFrameworkItem + if r, err := client.GetComplianceFrameworkItemRelationshipsById(ctx, r.qlient, data.FrameworkItemId.ValueString()); err != nil { + resp.Diagnostics.AddError("failed to find framework item", err.Error()) + return + } else { + i = r.ComplianceFrameworkItem + } + + data.RelationshipType = types.StringUnknown() + for _, item := range i.LibraryItems.InheritedEvidenceLibraryItems { + if item.Id == data.LibraryItemId.ValueString() { + data.RelationshipType = types.StringValue(string(client.LibraryItemToFrameworkItemRelationshipTypeInheritEvidence)) + break + } + } + for _, item := range i.LibraryItems.IgnoredEvidenceLibraryItems { + if item.Id == data.LibraryItemId.ValueString() { + data.RelationshipType = types.StringValue(string(client.LibraryItemToFrameworkItemRelationshipTypeIgnoreEvidence)) + break + } + } + + // Save updated data into Terraform state + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +// Update implements resource.Resource. +func (r *ComplianceRelationshipResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + var data *ComplianceRelationshipModel + + resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + _, err := client.UpdateComplianceLibraryItemToComplianceFrameworkItemRelationship(ctx, r.qlient, client.UpdateComplianceLibraryItemToComplianceFrameworkItemRelationshipInput{ + FrameworkItemId: data.FrameworkItemId.ValueString(), + LibraryItemId: data.LibraryItemId.ValueString(), + Updates: client.UpdateComplianceLibraryItemToComplianceFrameworkItemRelationshipFields{ + RelationshipType: client.LibraryItemToFrameworkItemRelationshipType(data.RelationshipType.ValueString()), + }, + }) + + if err != nil { + resp.Diagnostics.AddError("failed to create framework", err.Error()) + return + } + + data.Id = types.StringValue(fmt.Sprintf("%s-%s", data.LibraryItemId.ValueString(), data.FrameworkItemId.ValueString())) + + tflog.Trace(ctx, "Updated compliance relationship", + map[string]interface{}{"library_item_id": data.LibraryItemId, "framework_item_id": data.FrameworkItemId}) + + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} diff --git a/jupiterone/resource_compliance_relationship_test.go b/jupiterone/resource_compliance_relationship_test.go new file mode 100644 index 00000000..10ca9c57 --- /dev/null +++ b/jupiterone/resource_compliance_relationship_test.go @@ -0,0 +1,221 @@ +package jupiterone + +import ( + "context" + "fmt" + "strings" + "testing" + "time" + + "github.com/Khan/genqlient/graphql" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/jupiterone/terraform-provider-jupiterone/jupiterone/internal/client" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func testRelationshipConfig(frameworkItemId, libraryItemId string, relationship client.LibraryItemToFrameworkItemRelationshipType) string { + return fmt.Sprintf(` + resource jupiterone_compliance_relationship tf_acc_link_test { + framework_item_id = %q + library_item_id = %q + relationship_type = %q + } + `, frameworkItemId, libraryItemId, relationship) +} + +func TestComplianceRelationship_Basic(t *testing.T) { + ctx := context.TODO() + + recordingClient, directClient, cleanup := setupTestClients(ctx, t) + defer cleanup(t) + + // Because the library item is independent of the of the framework and + // child resources, terraform may perform the creations out of order, so + // creating them all in Steps.Config elements can be unpredictable. + // Necessary fixtures must be created before the tests and since the + // generated UUIDs are necessary, this must use the recordingClient. + frameworkId, frameworkItemId, libraryItemId, err := createTestRelationshipFixture(ctx, recordingClient) + require.NoError(t, err, "error creating test resources for compliancerelationship, resources may need to manually removed") + defer func() { + err := deleteTestRelationshipFixture(ctx, recordingClient, frameworkId, libraryItemId) + assert.NoError(t, err, "error removing test resources for compliancerelationship, resources may need to manually removed") + }() + + testRelationshipResourceName := "jupiterone_compliance_relationship.tf_acc_link_test" + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories(recordingClient), + CheckDestroy: testAccCheckRelationshipDestroy(ctx, directClient, frameworkItemId, libraryItemId), + Steps: []resource.TestStep{ + { + Config: testRelationshipConfig(frameworkItemId, libraryItemId, client.LibraryItemToFrameworkItemRelationshipTypeInheritEvidence), + Check: resource.ComposeTestCheckFunc( + testAccCheckRelationshipExists(ctx, directClient, frameworkItemId, libraryItemId, string(client.LibraryItemToFrameworkItemRelationshipTypeInheritEvidence)), + resource.TestCheckResourceAttrSet(testRelationshipResourceName, "id"), + resource.TestCheckResourceAttr(testRelationshipResourceName, "framework_item_id", frameworkItemId), + resource.TestCheckResourceAttr(testRelationshipResourceName, "library_item_id", libraryItemId), + resource.TestCheckResourceAttr(testRelationshipResourceName, "relationship_type", string(client.LibraryItemToFrameworkItemRelationshipTypeInheritEvidence)), + ), + }, + { + Config: testRelationshipConfig(frameworkItemId, libraryItemId, client.LibraryItemToFrameworkItemRelationshipTypeIgnoreEvidence), + Check: resource.ComposeTestCheckFunc( + testAccCheckRelationshipExists(ctx, directClient, frameworkItemId, libraryItemId, string(client.LibraryItemToFrameworkItemRelationshipTypeIgnoreEvidence)), + resource.TestCheckResourceAttrSet(testRelationshipResourceName, "id"), + resource.TestCheckResourceAttr(testRelationshipResourceName, "framework_item_id", frameworkItemId), + resource.TestCheckResourceAttr(testRelationshipResourceName, "library_item_id", libraryItemId), + resource.TestCheckResourceAttr(testRelationshipResourceName, "relationship_type", string(client.LibraryItemToFrameworkItemRelationshipTypeIgnoreEvidence)), + ), + }, + }, + }) +} + +func testAccCheckRelationshipExists(ctx context.Context, qlient graphql.Client, frameworkItemId, libraryItemId, relType string) resource.TestCheckFunc { + return func(s *terraform.State) error { + if qlient == nil { + return nil + } + + duration := 10 * time.Second + for _, r := range s.RootModule().Resources { + if r.Type != "jupiterone_compliancerelationship" { + continue + } + err := retry.RetryContext(ctx, duration, func() *retry.RetryError { + + resp, err := client.GetComplianceFrameworkItemRelationshipsById(ctx, qlient, frameworkItemId) + + if err == nil { + for _, l := range resp.ComplianceFrameworkItem.LibraryItems.InheritedEvidenceLibraryItems { + if l.Id == libraryItemId { + if relType == string(client.LibraryItemToFrameworkItemRelationshipTypeInheritEvidence) { + return nil + } + return retry.RetryableError(fmt.Errorf("Relationship should be `Inherit` relationship for relationship (framwork_item_id=%q, library_item_id=%q)", frameworkItemId, libraryItemId)) + } + } + for _, l := range resp.ComplianceFrameworkItem.LibraryItems.IgnoredEvidenceLibraryItems { + if l.Id == libraryItemId { + if relType == string(client.LibraryItemToFrameworkItemRelationshipTypeIgnoreEvidence) { + return nil + } + return retry.RetryableError(fmt.Errorf("Relationship should be `Ignore` relationship for relationship (framwork_item_id=%q, library_item_id=%q)", frameworkItemId, libraryItemId)) + } + } + return retry.RetryableError(fmt.Errorf("Relationship does not exist for fraemwork item (id=%q)", frameworkItemId)) + } + + if err != nil && strings.Contains(err.Error(), "Could not find compliance relationship for framework") { + return retry.RetryableError(err) + } + + return retry.NonRetryableError(err) + }) + + if err != nil { + return err + } + } + + return nil + } +} + +func testAccCheckRelationshipDestroy(ctx context.Context, qlient graphql.Client, frameworkItemId, libraryItemId string) resource.TestCheckFunc { + return func(s *terraform.State) error { + if qlient == nil { + return nil + } + + duration := 10 * time.Second + err := retry.RetryContext(ctx, duration, func() *retry.RetryError { + + resp, err := client.GetComplianceFrameworkItemRelationshipsById(ctx, qlient, frameworkItemId) + + if err == nil { + for _, l := range resp.ComplianceFrameworkItem.LibraryItems.InheritedEvidenceLibraryItems { + if l.Id == libraryItemId { + return retry.RetryableError(fmt.Errorf("Relationships still exists for framework item (id=%q)", frameworkItemId)) + } + } + for _, l := range resp.ComplianceFrameworkItem.LibraryItems.IgnoredEvidenceLibraryItems { + if l.Id == libraryItemId { + return retry.RetryableError(fmt.Errorf("Relationships still exists for framework item (id=%q)", frameworkItemId)) + } + } + return nil + } + + if err != nil && strings.Contains(err.Error(), "Could not find") { + return nil + } + + return retry.NonRetryableError(err) + }) + + if err != nil { + return err + } + + return nil + } +} + +func deleteTestRelationshipFixture(ctx context.Context, qlient graphql.Client, frameworkId, libraryItemId string) error { + _, err := client.DeleteComplianceFramework(ctx, qlient, client.DeleteComplianceFrameworkInput{Id: frameworkId}) + if err != nil { + return err + + } + + _, err = client.DeleteComplianceLibraryItem(ctx, qlient, libraryItemId) + return err +} + +func createTestRelationshipFixture(ctx context.Context, qlient graphql.Client) (frameworkId, frameworkItemId, libraryItemId string, err error) { + var f *client.CreateComplianceFrameworkResponse + f, err = client.CreateComplianceFramework(ctx, qlient, client.CreateComplianceFrameworkInput{ + Name: "tf-acc-test-framework", + Version: "1", + FrameworkType: client.ComplianceFrameworkTypeStandard, + }) + if err != nil { + return + } + frameworkId = f.CreateComplianceFramework.Id + + var g *client.CreateComplianceGroupResponse + g, err = client.CreateComplianceGroup(ctx, qlient, client.CreateComplianceGroupInput{ + Name: "tf-acc-test-group", + FrameworkId: frameworkId, + }) + if err != nil { + return + } + + var i *client.CreateComplianceFrameworkItemResponse + i, err = client.CreateComplianceFrameworkItem(ctx, qlient, client.CreateComplianceFrameworkItemInput{ + Name: "tf-acc-test-item", + FrameworkId: frameworkId, + GroupId: g.CreateComplianceGroup.Id, + }) + if err != nil { + return + } + frameworkItemId = i.CreateComplianceFrameworkItem.Id + + var l *client.CreateComplianceLibraryItemResponse + l, err = client.CreateComplianceLibraryItem(ctx, qlient, client.CreateComplianceLibraryItemInput{ + Name: "tf-acc-test-control", + }) + if err != nil { + return + } + libraryItemId = l.CreateComplianceLibraryItem.Id + + return frameworkId, frameworkItemId, libraryItemId, nil +} diff --git a/jupiterone/resource_group.go b/jupiterone/resource_group.go index 35242e33..9393dabb 100644 --- a/jupiterone/resource_group.go +++ b/jupiterone/resource_group.go @@ -6,11 +6,13 @@ import ( "fmt" "github.com/Khan/genqlient/graphql" + "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" "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/planmodifier" "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/hashicorp/terraform-plugin-log/tflog" "github.com/jupiterone/terraform-provider-jupiterone/jupiterone/internal/client" @@ -81,6 +83,9 @@ Refer to the resource_framework docs for example usage`, "framework_id": schema.StringAttribute{ Required: true, Description: "The internal ID of the framework this group is a part of", + Validators: []validator.String{ + stringvalidator.LengthBetween(UUIDStrLength, UUIDStrLength), + }, PlanModifiers: []planmodifier.String{ stringplanmodifier.UseStateForUnknown(), }, diff --git a/jupiterone/resource_question_test.go b/jupiterone/resource_question_test.go index 826ca0db..8f1d2446 100644 --- a/jupiterone/resource_question_test.go +++ b/jupiterone/resource_question_test.go @@ -9,8 +9,8 @@ import ( "time" "github.com/Khan/genqlient/graphql" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" + "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" "github.com/jupiterone/terraform-provider-jupiterone/jupiterone/internal/client"