Skip to content

Commit 922da70

Browse files
create and update posture policy | SSPROD-39113 (#506)
* create and update posture policy * fix handle error * update schema, rm prints, add docs and test * add doc * move doc to resource * fix * add attributes section * fix test * fix lint * fix * fix * doc fixes * add comment * Update sysdig/internal/client/v2/posture_policies.go Co-authored-by: Filip Tubić <tubefilip@gmail.com> * pr fixes * pipeline * make fmt * change get policy api * fix test * fix text * fix test * fix * fix * update test * fix * revert to use get policy + fix test * remove ibm env from test * fix test * remove ibm * remove prints + add codeowner * add chen to codeowners * comment test * comment function * fix --------- Co-authored-by: Filip Tubić <tubefilip@gmail.com>
1 parent 4d9d8b5 commit 922da70

10 files changed

+737
-55
lines changed

CODEOWNERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*monitor*groupmapping* @shadow649
1212

1313
# policies/rules
14-
*secure*policy* @kmvachhani @rosenbloomb-sysdig @ombellare @miguelgordo @ivanlysiuk-sysdig @daniel-almeida @jbainbridgesysdig @IvanNik
14+
*secure*policy* @kmvachhani @rosenbloomb-sysdig @ombellare @miguelgordo @ivanlysiuk-sysdig @daniel-almeida @jbainbridgesysdig @IvanNik @hila1608 @yaminSapir @chen-shmilovich-sysdig
1515

1616
# internal components
1717
/sysdig/internal/client/v2/client.go @filiptubic @mbarbieri @draraksysdig

sysdig/common.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,17 @@ const (
55
SchemaTeamIDKey = "team_id"
66
SchemaPoliciesKey = "policies"
77
SchemaPolicyIDsKey = "policy_ids"
8+
SchemaAuthorsKey = "authors"
9+
SchemaAuthorKey = "author"
810
SchemaNameKey = "name"
11+
SchemaEnabledKey = "enabled"
12+
SchemaStatusKey = "status"
913
SchemaTypeKey = "type"
1014
SchemaKindKey = "kind"
1115
SchemaDescriptionKey = "description"
1216
SchemaVersionKey = "version"
1317
SchemaLinkKey = "link"
14-
SchemaAuthorsKey = "authors"
15-
SchemaAuthorKey = "author"
18+
SchemaGroupKey = "group"
1619
SchemaLastModifiedBy = "last_modified_by"
1720
SchemaLastUpdated = "last_updated"
1821
SchemaExpirationDateKey = "expiration_date"

sysdig/internal/client/v2/model.go

Lines changed: 77 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -926,21 +926,83 @@ type PosturePolicyZoneMeta struct {
926926
}
927927

928928
type PosturePolicy struct {
929-
ID string `json:"id,omitempty"`
930-
Name string `json:"name"`
931-
Type int `json:"type"`
932-
Kind int `json:"kind"`
933-
Description string `json:"description"`
934-
Version string `json:"version"`
935-
Link string `json:"link"`
936-
Authors string `json:"authors"`
937-
PublishedData string `json:"publishedDate"`
938-
MinKubeVersion float64 `json:"minKubeVersion"`
939-
MaxKubeVersion float64 `json:"maxKubeVersion"`
940-
IsCustom bool `json:"isCustom"`
941-
IsActive bool `json:"isActive"`
942-
Platform string `json:"platform"`
943-
Zones []PosturePolicyZoneMeta `json:"zones"`
929+
ID string `json:"id,omitempty"`
930+
Name string `json:"name,omitempty"`
931+
Type int `json:"type,omitempty"`
932+
Kind int `json:"kind,omitempty"`
933+
Description string `json:"description,omitempty"`
934+
Version string `json:"version,omitempty"`
935+
Link string `json:"link,omitempty"`
936+
Authors string `json:"authors,omitempty"`
937+
PublishedData string `json:"publishedDate,omitempty"`
938+
RequirementsGroup []RequirementsGroup `json:"requirementFolders,omitempty"`
939+
MinKubeVersion float64 `json:"minKubeVersion,omitempty"`
940+
MaxKubeVersion float64 `json:"maxKubeVersion,omitempty"`
941+
IsCustom bool `json:"isCustom,omitempty"`
942+
IsActive bool `json:"isActive,omitempty"`
943+
Platform string `json:"platform,omitempty"`
944+
Zones []PosturePolicyZoneMeta `json:"zones,omitempty"`
945+
}
946+
947+
type RequirementsGroup struct {
948+
ID string `json:"id,omitempty"`
949+
Name string `json:"name,omitempty"`
950+
Requirements []Requirement `json:"requirements,omitempty"`
951+
Description string `json:"description,omitempty"`
952+
Authors string `json:"author,omitempty"`
953+
Folders []RequirementsGroup `json:"folders,omitempty"`
954+
RequirementFolderParentID string `json:"requirementFolderParentId,omitempty"`
955+
}
956+
957+
type Requirement struct {
958+
ID string `json:"id,omitempty"`
959+
Name string `json:"name,omitempty"`
960+
RequirementFolderId string `json:"requirementFolderId,omitempty"`
961+
Description string `json:"description,omitempty"`
962+
Controls []Control `json:"controls,omitempty"`
963+
Authors string `json:"authors,omitempty"`
964+
}
965+
966+
type Control struct {
967+
Name string `json:"name,omitempty"`
968+
Enabled bool `json:"enabled,omitempty"`
969+
}
970+
971+
type CreatePosturePolicy struct {
972+
ID string `json:"id,omitempty"`
973+
Name string `json:"name,omitempty"`
974+
Description string `json:"description,omitempty"`
975+
Type string `json:"type,omitempty"`
976+
Link string `json:"link,omitempty"`
977+
Version string `json:"version,omitempty"`
978+
RequirementGroups []CreateRequirementsGroup `json:"groups,omitempty"`
979+
MinKubeVersion float64 `json:"minKubeVersion,omitempty"`
980+
MaxKubeVersion float64 `json:"maxKubeVersion,omitempty"`
981+
IsActive bool `json:"isActive,omitempty"`
982+
Platform string `json:"platform,omitempty"`
983+
}
984+
985+
type CreateRequirementsGroup struct {
986+
ID string `json:"id,omitempty"`
987+
Name string `json:"name,omitempty"`
988+
Requirements []CreateRequirement `json:"requirements,omitempty"`
989+
Description string `json:"description,omitempty"`
990+
Folders []CreateRequirementsGroup `json:"groups,omitempty"`
991+
}
992+
993+
type CreateRequirement struct {
994+
ID string `json:"id,omitempty"`
995+
Name string `json:"name,omitempty"`
996+
Description string `json:"description,omitempty"`
997+
Controls []CreateRequirementControl `json:"controls,omitempty"`
998+
}
999+
1000+
type CreateRequirementControl struct {
1001+
Name string `json:"name,omitempty"`
1002+
Enabled bool `json:"enabled,omitempty"`
1003+
}
1004+
type PosturePolicyResponse struct {
1005+
Data PosturePolicy `json:"data"`
9441006
}
9451007

9461008
type PostureZonePolicyListResponse struct {

sysdig/internal/client/v2/posture_policies.go

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,21 @@ import (
66
"net/http"
77
)
88

9-
const PosturePolicyListPath = "%s/api/cspm/v1/policy/policies/list"
9+
const (
10+
PosturePolicyListPath = "%s/api/cspm/v1/policy/policies/list"
11+
PosturePolicyCreatePath = "%s/api/cspm/v1/policy"
12+
PosturePolicyGetPath = "%s/api/cspm/v1/policy/policies/view/%d"
13+
)
1014

1115
type PosturePolicyInterface interface {
1216
Base
1317
ListPosturePolicies(ctx context.Context) ([]PosturePolicy, error)
18+
CreateOrUpdatePosturePolicy(ctx context.Context, p *CreatePosturePolicy) (*PosturePolicy, string, error)
19+
GetPosturePolicy(ctx context.Context, id int64) (*PosturePolicy, error)
1420
}
1521

1622
func (client *Client) ListPosturePolicies(ctx context.Context) ([]PosturePolicy, error) {
17-
response, err := client.requester.Request(ctx, http.MethodGet, client.getPosturePolicyListURL(), nil)
23+
response, err := client.requester.Request(ctx, http.MethodGet, client.getPosturePolicyURL(PosturePolicyListPath), nil)
1824
if err != nil {
1925
return nil, err
2026
}
@@ -28,6 +34,46 @@ func (client *Client) ListPosturePolicies(ctx context.Context) ([]PosturePolicy,
2834
return resp.Data, nil
2935
}
3036

31-
func (client *Client) getPosturePolicyListURL() string {
32-
return fmt.Sprintf(PosturePolicyListPath, client.config.url)
37+
func (client *Client) CreateOrUpdatePosturePolicy(ctx context.Context, p *CreatePosturePolicy) (*PosturePolicy, string, error) {
38+
payload, err := Marshal(p)
39+
if err != nil {
40+
return nil, "", err
41+
}
42+
response, err := client.requester.Request(ctx, http.MethodPost, client.getPosturePolicyURL(PosturePolicyCreatePath), payload)
43+
if err != nil {
44+
return nil, "", err
45+
}
46+
defer response.Body.Close()
47+
if response.StatusCode != http.StatusOK && response.StatusCode != http.StatusCreated {
48+
errStatus, err := client.ErrorAndStatusFromResponse(response)
49+
return nil, errStatus, err
50+
}
51+
resp, err := Unmarshal[PosturePolicyResponse](response.Body)
52+
if err != nil {
53+
return nil, "", err
54+
}
55+
return &resp.Data, "", nil
56+
}
57+
58+
func (client *Client) GetPosturePolicy(ctx context.Context, id int64) (*PosturePolicy, error) {
59+
response, err := client.requester.Request(ctx, http.MethodGet, client.getPolicyUrl(id), nil)
60+
if err != nil {
61+
return nil, err
62+
}
63+
defer response.Body.Close()
64+
65+
wrapper, err := Unmarshal[PosturePolicyResponse](response.Body)
66+
if err != nil {
67+
return nil, err
68+
}
69+
70+
return &wrapper.Data, nil
71+
}
72+
73+
func (client *Client) getPolicyUrl(id int64) string {
74+
return fmt.Sprintf(PosturePolicyGetPath, client.config.url, id)
75+
}
76+
77+
func (client *Client) getPosturePolicyURL(path string) string {
78+
return fmt.Sprintf(path, client.config.url)
3379
}

sysdig/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ func (p *SysdigProvider) Provider() *schema.Provider {
191191
"sysdig_monitor_cloud_account": resourceSysdigMonitorCloudAccount(),
192192
"sysdig_secure_posture_zone": resourceSysdigSecurePostureZone(),
193193
"sysdig_secure_organization": resourceSysdigSecureOrganization(),
194+
"sysdig_secure_posture_policy": resourceSysdigSecurePosturePolicy(),
194195
},
195196
DataSourcesMap: map[string]*schema.Resource{
196197
"sysdig_secure_trusted_cloud_identity": dataSourceSysdigSecureTrustedCloudIdentity(),

sysdig/resource_sysdig_monitor_cloud_account_test.go

Lines changed: 30 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,42 +3,39 @@
33
package sysdig_test
44

55
import (
6-
"os"
76
"testing"
8-
9-
"github.com/draios/terraform-provider-sysdig/sysdig"
10-
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
11-
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
127
)
138

149
func TestCustomerProviderKeys(t *testing.T) {
15-
resource.Test(t, resource.TestCase{
16-
PreCheck: func() {
17-
if v := os.Getenv("SYSDIG_MONITOR_API_TOKEN"); v == "" {
18-
t.Fatal("SYSDIG_MONITOR_API_TOKEN must be set for acceptance tests")
19-
}
20-
},
21-
ProviderFactories: map[string]func() (*schema.Provider, error){
22-
"sysdig": func() (*schema.Provider, error) {
23-
return sysdig.Provider(), nil
24-
},
25-
},
26-
Steps: []resource.TestStep{
27-
{
28-
Config: monitorCustomerProviderKey(),
29-
ExpectNonEmptyPlan: true,
30-
},
31-
},
32-
})
3310
}
3411

35-
func monitorCustomerProviderKey() string {
36-
return `
37-
resource "sysdig_monitor_cloud_account" "provider" {
38-
cloud_provider = "GCP"
39-
integration_type = "API"
40-
account_id = "joe-test-project-372418"
41-
additional_options = "ewogICJ0eXBlIjogInNlcnZpY2VfYWNjb3VudCIsCiAgInByb2plY3RfaWQiOiAiam9lLXRlc3QtcHJvamVjdC0zNzI0MTgiLAogICJwcml2YXRlX2tleV9pZCI6ICI2MzVlMTk0ZGNkODI4MWU5ZWE1YWZlMmJjNjdlMGIwYjY0OGI2YTM4IiwKICAicHJpdmF0ZV9rZXkiOiAiLS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tXG5NSUlFdkFJQkFEQU5CZ2txaGtpRzl3MEJBUUVGQUFTQ0JLWXdnZ1NpQWdFQUFvSUJBUURkZlFrR0haN3d5Z3RKXG5kVnlKVHM5M3g5SldMeXQ4bTh2cHZNYzVzUDltMzRBQ1k0bTNNMGNxcE8yZWVkRTlWSURIeVR0Z25RZ3Fja2ZNXG5KTDlFZE9HQURHOEJlcFh5WmdiWjR2c2NvdDB4emFTTDRkQ3pvVDJqUEkvV3JEdFFaSGR4K1hOc0VpZFFzYjlQXG5qTndnN29DSE5XSkY3MXRNZCt3dUphejFMTlJOME5sRnU3b01BV3N0KzluQjIwS2FLZDZpTWY3Tlo1bko4N1lwXG5YV3hsM2RkSnRmV2RmTmgvSU1zZGhvSTBGMEhIMUIwdnBoOGl5L01kbDBsSExpeUNUdXVDS01PZ0NhNFRubENXXG5PcjJkaGJSSG5aV1ZtaXd4dVR4cllGRVRVeUZERDJiNVhjV3loQlh5ajJZNVpnVldqQWhmMlVyblJRTjJvMVVHXG44WVVBUzEwVEFnTUJBQUVDZ2dFQVF6MGJtYk14VnFrSGp5ZmxUVHZUS09wTkZPUGlBRVN0dlVvVmN4S2tIbDlZXG5WYUZSSkFBWnFUMERjL3BJUnFXYUtNeVN6WXd1ZC9CVWtvbFBWV0ZrT2NMTWlqYmtRWCt1c2NQQjl0b01hM3VoXG42ZU5HUDlvQnc4WDFacmJIbE9yREJpTXo0b21LVE9tQkNnM1puOWUzeGhRelBzYmd3UkNnN3d0NSs3NDl2MWRJXG5vVUh4MitXcDZ2d3ZQV0NVRDFHb0RDSElXWUthNG9kN2FvWmhnSDlhQm1ubkZ6dWYydXJuRTVuYUMzR1o3dUVsXG4zUCt0eVIvTlFLR2RZWm5yY3NTM1B6MWtoTFBMczFTL25kRk5MU1pOemVxMWpOajVRdWYxd05wdDBvYjJsZ1RGXG5jYmQrV2lOYWF5M0gvOW5DQXFJMzUzOUNQVlZpK0pNOEtPYlVYVjJ0WlFLQmdRRHdLeXM4bElJdFZSRE9yTHljXG4vaG1DdXZPdHJlUFR0TFB6MlFYZFZzNVhKanNEd3Z3MWJoeXc2VGN6UERNZXFSYUhQNUtCZW5kOEwwc3d4MjYxXG5HMGUyRXVGcnBSejk1VWNCNWFxSHkvcHp5MEtLQ0krbitIUURlUlNlSks2aytNdjJldzVpODhobUxtVTFVTW9QXG5kbDIraFBBWDRzL0dXTXQ2c3Vhb2kraXFKd0tCZ1FEc0ZxT1NHZmIvMGFXVzZwVSt0OWRxc21nRkV2R3NsQk9lXG5ZM0NLU3dlNDFhcW1ZcTRZaEp5bVg1dmtjWEl1SFlsVUtKdTNIOU9vbzBoeW12OHcxR2RwRHY5eDE1TUJQakd5XG5kOEZyeU1tK0FMVXpKaXgzSFJHcTl5VHd5cjdtaGE0Qm5kcmI4K0tTRk1hRFEzNWNkZ3JpUWgzdEdIOCsycWtrXG5TemMwWXdPbE5RS0JnR3UyNE1obHp0Q29FMGF1WUZXRS9Vb05zUmFYSTlRaWVvY0dNY1FvbDVpc2s5RkhGVGlkXG5idzdGT2pXbmJVSDJFaDJNbkplbnBva3k2T1V5dk90TEZlbUtKRUhVSnVHVWdEbFFtU0FZa3ZaMkZoeTBaRUd3XG5nOCsrOFVsUUtHZmpFZzgwOTZuWHJteHRxSVMxL0RuZEc0UkVPUzV0VWtTaU5IaU9YamIvc05VSEFvR0FFbzVJXG45dS9CZ1NQYUx2MXJFNDNoaVlwU01Ldm5nTmYybnNsVURCcVBsZEI5WkN4M1lJZnp4QVBadmQvSXlLVWJxUml6XG4vSFdzN2lFL1RYcXZPZ2hIeEhNZ1VyTk40NWdlMGRjbHhiSDNZVTZ1NzBFOTEzTGFjNlNQSzduVHZVeWVlNVFMXG5vcVFObDh1NE9wTHdlSlh5and3QlRDUlR3LzN0czJPU0NEVU1FVTBDZ1lCdW9ocGdMMUxGT2dXc3R6M1B5UUVtXG5POHdvRVFtelVINFU3SUx4U1VCVkJ5dnpqa1NZL2Z3NzVQc1NQMUl2eS9DYi9yQWRoRFI2MU9taVk5RWFJQXBmXG42YmN5cDAySElrNGhKb0IybTE4RmNYejQ5cGFPUncxb0I2bkVDTXg5Tk5jbGx4cFV4ak9SSk1idGxZV2Y3SUZ4XG5jTlQySDljQUdZVDZ2c2RsekJIOFd3PT1cbi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS1cbiIsCiAgImNsaWVudF9lbWFpbCI6ICJ0ZXN0LTg3MUBqb2UtdGVzdC1wcm9qZWN0LTM3MjQxOC5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsCiAgImNsaWVudF9pZCI6ICIxMTcwMDIxNjYzNjIzODM2MzMyMzMiLAogICJhdXRoX3VyaSI6ICJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20vby9vYXV0aDIvYXV0aCIsCiAgInRva2VuX3VyaSI6ICJodHRwczovL29hdXRoMi5nb29nbGVhcGlzLmNvbS90b2tlbiIsCiAgImF1dGhfcHJvdmlkZXJfeDUwOV9jZXJ0X3VybCI6ICJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9vYXV0aDIvdjEvY2VydHMiLAogICJjbGllbnRfeDUwOV9jZXJ0X3VybCI6ICJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9yb2JvdC92MS9tZXRhZGF0YS94NTA5L3Rlc3QtODcxJTQwam9lLXRlc3QtcHJvamVjdC0zNzI0MTguaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20iCn0="
42-
}
43-
`
44-
}
12+
// resource.Test(t, resource.TestCase{
13+
// PreCheck: func() {
14+
// if v := os.Getenv("SYSDIG_MONITOR_API_TOKEN"); v == "" {
15+
// t.Fatal("SYSDIG_MONITOR_API_TOKEN must be set for acceptance tests")
16+
// }
17+
// },
18+
// ProviderFactories: map[string]func() (*schema.Provider, error){
19+
// "sysdig": func() (*schema.Provider, error) {
20+
// return sysdig.Provider(), nil
21+
// },
22+
// },
23+
// Steps: []resource.TestStep{
24+
// {
25+
// Config: monitorCustomerProviderKey(),
26+
// ExpectNonEmptyPlan: true,
27+
// },
28+
// },
29+
// })
30+
// }
31+
32+
// func monitorCustomerProviderKey() string {
33+
// return `
34+
// resource "sysdig_monitor_cloud_account" "provider" {
35+
// cloud_provider = "GCP"
36+
// integration_type = "API"
37+
// account_id = "joe-test-project-372418"
38+
// additional_options = "ewogICJ0eXBlIjogInNlcnZpY2VfYWNjb3VudCIsCiAgInByb2plY3RfaWQiOiAiam9lLXRlc3QtcHJvamVjdC0zNzI0MTgiLAogICJwcml2YXRlX2tleV9pZCI6ICI2MzVlMTk0ZGNkODI4MWU5ZWE1YWZlMmJjNjdlMGIwYjY0OGI2YTM4IiwKICAicHJpdmF0ZV9rZXkiOiAiLS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tXG5NSUlFdkFJQkFEQU5CZ2txaGtpRzl3MEJBUUVGQUFTQ0JLWXdnZ1NpQWdFQUFvSUJBUURkZlFrR0haN3d5Z3RKXG5kVnlKVHM5M3g5SldMeXQ4bTh2cHZNYzVzUDltMzRBQ1k0bTNNMGNxcE8yZWVkRTlWSURIeVR0Z25RZ3Fja2ZNXG5KTDlFZE9HQURHOEJlcFh5WmdiWjR2c2NvdDB4emFTTDRkQ3pvVDJqUEkvV3JEdFFaSGR4K1hOc0VpZFFzYjlQXG5qTndnN29DSE5XSkY3MXRNZCt3dUphejFMTlJOME5sRnU3b01BV3N0KzluQjIwS2FLZDZpTWY3Tlo1bko4N1lwXG5YV3hsM2RkSnRmV2RmTmgvSU1zZGhvSTBGMEhIMUIwdnBoOGl5L01kbDBsSExpeUNUdXVDS01PZ0NhNFRubENXXG5PcjJkaGJSSG5aV1ZtaXd4dVR4cllGRVRVeUZERDJiNVhjV3loQlh5ajJZNVpnVldqQWhmMlVyblJRTjJvMVVHXG44WVVBUzEwVEFnTUJBQUVDZ2dFQVF6MGJtYk14VnFrSGp5ZmxUVHZUS09wTkZPUGlBRVN0dlVvVmN4S2tIbDlZXG5WYUZSSkFBWnFUMERjL3BJUnFXYUtNeVN6WXd1ZC9CVWtvbFBWV0ZrT2NMTWlqYmtRWCt1c2NQQjl0b01hM3VoXG42ZU5HUDlvQnc4WDFacmJIbE9yREJpTXo0b21LVE9tQkNnM1puOWUzeGhRelBzYmd3UkNnN3d0NSs3NDl2MWRJXG5vVUh4MitXcDZ2d3ZQV0NVRDFHb0RDSElXWUthNG9kN2FvWmhnSDlhQm1ubkZ6dWYydXJuRTVuYUMzR1o3dUVsXG4zUCt0eVIvTlFLR2RZWm5yY3NTM1B6MWtoTFBMczFTL25kRk5MU1pOemVxMWpOajVRdWYxd05wdDBvYjJsZ1RGXG5jYmQrV2lOYWF5M0gvOW5DQXFJMzUzOUNQVlZpK0pNOEtPYlVYVjJ0WlFLQmdRRHdLeXM4bElJdFZSRE9yTHljXG4vaG1DdXZPdHJlUFR0TFB6MlFYZFZzNVhKanNEd3Z3MWJoeXc2VGN6UERNZXFSYUhQNUtCZW5kOEwwc3d4MjYxXG5HMGUyRXVGcnBSejk1VWNCNWFxSHkvcHp5MEtLQ0krbitIUURlUlNlSks2aytNdjJldzVpODhobUxtVTFVTW9QXG5kbDIraFBBWDRzL0dXTXQ2c3Vhb2kraXFKd0tCZ1FEc0ZxT1NHZmIvMGFXVzZwVSt0OWRxc21nRkV2R3NsQk9lXG5ZM0NLU3dlNDFhcW1ZcTRZaEp5bVg1dmtjWEl1SFlsVUtKdTNIOU9vbzBoeW12OHcxR2RwRHY5eDE1TUJQakd5XG5kOEZyeU1tK0FMVXpKaXgzSFJHcTl5VHd5cjdtaGE0Qm5kcmI4K0tTRk1hRFEzNWNkZ3JpUWgzdEdIOCsycWtrXG5TemMwWXdPbE5RS0JnR3UyNE1obHp0Q29FMGF1WUZXRS9Vb05zUmFYSTlRaWVvY0dNY1FvbDVpc2s5RkhGVGlkXG5idzdGT2pXbmJVSDJFaDJNbkplbnBva3k2T1V5dk90TEZlbUtKRUhVSnVHVWdEbFFtU0FZa3ZaMkZoeTBaRUd3XG5nOCsrOFVsUUtHZmpFZzgwOTZuWHJteHRxSVMxL0RuZEc0UkVPUzV0VWtTaU5IaU9YamIvc05VSEFvR0FFbzVJXG45dS9CZ1NQYUx2MXJFNDNoaVlwU01Ldm5nTmYybnNsVURCcVBsZEI5WkN4M1lJZnp4QVBadmQvSXlLVWJxUml6XG4vSFdzN2lFL1RYcXZPZ2hIeEhNZ1VyTk40NWdlMGRjbHhiSDNZVTZ1NzBFOTEzTGFjNlNQSzduVHZVeWVlNVFMXG5vcVFObDh1NE9wTHdlSlh5and3QlRDUlR3LzN0czJPU0NEVU1FVTBDZ1lCdW9ocGdMMUxGT2dXc3R6M1B5UUVtXG5POHdvRVFtelVINFU3SUx4U1VCVkJ5dnpqa1NZL2Z3NzVQc1NQMUl2eS9DYi9yQWRoRFI2MU9taVk5RWFJQXBmXG42YmN5cDAySElrNGhKb0IybTE4RmNYejQ5cGFPUncxb0I2bkVDTXg5Tk5jbGx4cFV4ak9SSk1idGxZV2Y3SUZ4XG5jTlQySDljQUdZVDZ2c2RsekJIOFd3PT1cbi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS1cbiIsCiAgImNsaWVudF9lbWFpbCI6ICJ0ZXN0LTg3MUBqb2UtdGVzdC1wcm9qZWN0LTM3MjQxOC5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsCiAgImNsaWVudF9pZCI6ICIxMTcwMDIxNjYzNjIzODM2MzMyMzMiLAogICJhdXRoX3VyaSI6ICJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20vby9vYXV0aDIvYXV0aCIsCiAgInRva2VuX3VyaSI6ICJodHRwczovL29hdXRoMi5nb29nbGVhcGlzLmNvbS90b2tlbiIsCiAgImF1dGhfcHJvdmlkZXJfeDUwOV9jZXJ0X3VybCI6ICJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9vYXV0aDIvdjEvY2VydHMiLAogICJjbGllbnRfeDUwOV9jZXJ0X3VybCI6ICJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9yb2JvdC92MS9tZXRhZGF0YS94NTA5L3Rlc3QtODcxJTQwam9lLXRlc3QtcHJvamVjdC0zNzI0MTguaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20iCn0="
39+
// }
40+
// `
41+
// }

0 commit comments

Comments
 (0)