Skip to content

Commit

Permalink
create and update posture policy | SSPROD-39113 (#506)
Browse files Browse the repository at this point in the history
* 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ć <[email protected]>

* 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ć <[email protected]>
  • Loading branch information
hila-krut-sysdig and filiptubic authored May 22, 2024
1 parent 4d9d8b5 commit 922da70
Show file tree
Hide file tree
Showing 10 changed files with 737 additions and 55 deletions.
2 changes: 1 addition & 1 deletion CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
*monitor*groupmapping* @shadow649

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

# internal components
/sysdig/internal/client/v2/client.go @filiptubic @mbarbieri @draraksysdig
Expand Down
7 changes: 5 additions & 2 deletions sysdig/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,17 @@ const (
SchemaTeamIDKey = "team_id"
SchemaPoliciesKey = "policies"
SchemaPolicyIDsKey = "policy_ids"
SchemaAuthorsKey = "authors"
SchemaAuthorKey = "author"
SchemaNameKey = "name"
SchemaEnabledKey = "enabled"
SchemaStatusKey = "status"
SchemaTypeKey = "type"
SchemaKindKey = "kind"
SchemaDescriptionKey = "description"
SchemaVersionKey = "version"
SchemaLinkKey = "link"
SchemaAuthorsKey = "authors"
SchemaAuthorKey = "author"
SchemaGroupKey = "group"
SchemaLastModifiedBy = "last_modified_by"
SchemaLastUpdated = "last_updated"
SchemaExpirationDateKey = "expiration_date"
Expand Down
92 changes: 77 additions & 15 deletions sysdig/internal/client/v2/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -926,21 +926,83 @@ type PosturePolicyZoneMeta struct {
}

type PosturePolicy struct {
ID string `json:"id,omitempty"`
Name string `json:"name"`
Type int `json:"type"`
Kind int `json:"kind"`
Description string `json:"description"`
Version string `json:"version"`
Link string `json:"link"`
Authors string `json:"authors"`
PublishedData string `json:"publishedDate"`
MinKubeVersion float64 `json:"minKubeVersion"`
MaxKubeVersion float64 `json:"maxKubeVersion"`
IsCustom bool `json:"isCustom"`
IsActive bool `json:"isActive"`
Platform string `json:"platform"`
Zones []PosturePolicyZoneMeta `json:"zones"`
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Type int `json:"type,omitempty"`
Kind int `json:"kind,omitempty"`
Description string `json:"description,omitempty"`
Version string `json:"version,omitempty"`
Link string `json:"link,omitempty"`
Authors string `json:"authors,omitempty"`
PublishedData string `json:"publishedDate,omitempty"`
RequirementsGroup []RequirementsGroup `json:"requirementFolders,omitempty"`
MinKubeVersion float64 `json:"minKubeVersion,omitempty"`
MaxKubeVersion float64 `json:"maxKubeVersion,omitempty"`
IsCustom bool `json:"isCustom,omitempty"`
IsActive bool `json:"isActive,omitempty"`
Platform string `json:"platform,omitempty"`
Zones []PosturePolicyZoneMeta `json:"zones,omitempty"`
}

type RequirementsGroup struct {
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Requirements []Requirement `json:"requirements,omitempty"`
Description string `json:"description,omitempty"`
Authors string `json:"author,omitempty"`
Folders []RequirementsGroup `json:"folders,omitempty"`
RequirementFolderParentID string `json:"requirementFolderParentId,omitempty"`
}

type Requirement struct {
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
RequirementFolderId string `json:"requirementFolderId,omitempty"`
Description string `json:"description,omitempty"`
Controls []Control `json:"controls,omitempty"`
Authors string `json:"authors,omitempty"`
}

type Control struct {
Name string `json:"name,omitempty"`
Enabled bool `json:"enabled,omitempty"`
}

type CreatePosturePolicy struct {
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
Type string `json:"type,omitempty"`
Link string `json:"link,omitempty"`
Version string `json:"version,omitempty"`
RequirementGroups []CreateRequirementsGroup `json:"groups,omitempty"`
MinKubeVersion float64 `json:"minKubeVersion,omitempty"`
MaxKubeVersion float64 `json:"maxKubeVersion,omitempty"`
IsActive bool `json:"isActive,omitempty"`
Platform string `json:"platform,omitempty"`
}

type CreateRequirementsGroup struct {
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Requirements []CreateRequirement `json:"requirements,omitempty"`
Description string `json:"description,omitempty"`
Folders []CreateRequirementsGroup `json:"groups,omitempty"`
}

type CreateRequirement struct {
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
Controls []CreateRequirementControl `json:"controls,omitempty"`
}

type CreateRequirementControl struct {
Name string `json:"name,omitempty"`
Enabled bool `json:"enabled,omitempty"`
}
type PosturePolicyResponse struct {
Data PosturePolicy `json:"data"`
}

type PostureZonePolicyListResponse struct {
Expand Down
54 changes: 50 additions & 4 deletions sysdig/internal/client/v2/posture_policies.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,21 @@ import (
"net/http"
)

const PosturePolicyListPath = "%s/api/cspm/v1/policy/policies/list"
const (
PosturePolicyListPath = "%s/api/cspm/v1/policy/policies/list"
PosturePolicyCreatePath = "%s/api/cspm/v1/policy"
PosturePolicyGetPath = "%s/api/cspm/v1/policy/policies/view/%d"
)

type PosturePolicyInterface interface {
Base
ListPosturePolicies(ctx context.Context) ([]PosturePolicy, error)
CreateOrUpdatePosturePolicy(ctx context.Context, p *CreatePosturePolicy) (*PosturePolicy, string, error)
GetPosturePolicy(ctx context.Context, id int64) (*PosturePolicy, error)
}

func (client *Client) ListPosturePolicies(ctx context.Context) ([]PosturePolicy, error) {
response, err := client.requester.Request(ctx, http.MethodGet, client.getPosturePolicyListURL(), nil)
response, err := client.requester.Request(ctx, http.MethodGet, client.getPosturePolicyURL(PosturePolicyListPath), nil)
if err != nil {
return nil, err
}
Expand All @@ -28,6 +34,46 @@ func (client *Client) ListPosturePolicies(ctx context.Context) ([]PosturePolicy,
return resp.Data, nil
}

func (client *Client) getPosturePolicyListURL() string {
return fmt.Sprintf(PosturePolicyListPath, client.config.url)
func (client *Client) CreateOrUpdatePosturePolicy(ctx context.Context, p *CreatePosturePolicy) (*PosturePolicy, string, error) {
payload, err := Marshal(p)
if err != nil {
return nil, "", err
}
response, err := client.requester.Request(ctx, http.MethodPost, client.getPosturePolicyURL(PosturePolicyCreatePath), payload)
if err != nil {
return nil, "", err
}
defer response.Body.Close()
if response.StatusCode != http.StatusOK && response.StatusCode != http.StatusCreated {
errStatus, err := client.ErrorAndStatusFromResponse(response)
return nil, errStatus, err
}
resp, err := Unmarshal[PosturePolicyResponse](response.Body)
if err != nil {
return nil, "", err
}
return &resp.Data, "", nil
}

func (client *Client) GetPosturePolicy(ctx context.Context, id int64) (*PosturePolicy, error) {
response, err := client.requester.Request(ctx, http.MethodGet, client.getPolicyUrl(id), nil)
if err != nil {
return nil, err
}
defer response.Body.Close()

wrapper, err := Unmarshal[PosturePolicyResponse](response.Body)
if err != nil {
return nil, err
}

return &wrapper.Data, nil
}

func (client *Client) getPolicyUrl(id int64) string {
return fmt.Sprintf(PosturePolicyGetPath, client.config.url, id)
}

func (client *Client) getPosturePolicyURL(path string) string {
return fmt.Sprintf(path, client.config.url)
}
1 change: 1 addition & 0 deletions sysdig/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ func (p *SysdigProvider) Provider() *schema.Provider {
"sysdig_monitor_cloud_account": resourceSysdigMonitorCloudAccount(),
"sysdig_secure_posture_zone": resourceSysdigSecurePostureZone(),
"sysdig_secure_organization": resourceSysdigSecureOrganization(),
"sysdig_secure_posture_policy": resourceSysdigSecurePosturePolicy(),
},
DataSourcesMap: map[string]*schema.Resource{
"sysdig_secure_trusted_cloud_identity": dataSourceSysdigSecureTrustedCloudIdentity(),
Expand Down
63 changes: 30 additions & 33 deletions sysdig/resource_sysdig_monitor_cloud_account_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,39 @@
package sysdig_test

import (
"os"
"testing"

"github.com/draios/terraform-provider-sysdig/sysdig"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func TestCustomerProviderKeys(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() {
if v := os.Getenv("SYSDIG_MONITOR_API_TOKEN"); v == "" {
t.Fatal("SYSDIG_MONITOR_API_TOKEN must be set for acceptance tests")
}
},
ProviderFactories: map[string]func() (*schema.Provider, error){
"sysdig": func() (*schema.Provider, error) {
return sysdig.Provider(), nil
},
},
Steps: []resource.TestStep{
{
Config: monitorCustomerProviderKey(),
ExpectNonEmptyPlan: true,
},
},
})
}

func monitorCustomerProviderKey() string {
return `
resource "sysdig_monitor_cloud_account" "provider" {
cloud_provider = "GCP"
integration_type = "API"
account_id = "joe-test-project-372418"
additional_options = "ewogICJ0eXBlIjogInNlcnZpY2VfYWNjb3VudCIsCiAgInByb2plY3RfaWQiOiAiam9lLXRlc3QtcHJvamVjdC0zNzI0MTgiLAogICJwcml2YXRlX2tleV9pZCI6ICI2MzVlMTk0ZGNkODI4MWU5ZWE1YWZlMmJjNjdlMGIwYjY0OGI2YTM4IiwKICAicHJpdmF0ZV9rZXkiOiAiLS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tXG5NSUlFdkFJQkFEQU5CZ2txaGtpRzl3MEJBUUVGQUFTQ0JLWXdnZ1NpQWdFQUFvSUJBUURkZlFrR0haN3d5Z3RKXG5kVnlKVHM5M3g5SldMeXQ4bTh2cHZNYzVzUDltMzRBQ1k0bTNNMGNxcE8yZWVkRTlWSURIeVR0Z25RZ3Fja2ZNXG5KTDlFZE9HQURHOEJlcFh5WmdiWjR2c2NvdDB4emFTTDRkQ3pvVDJqUEkvV3JEdFFaSGR4K1hOc0VpZFFzYjlQXG5qTndnN29DSE5XSkY3MXRNZCt3dUphejFMTlJOME5sRnU3b01BV3N0KzluQjIwS2FLZDZpTWY3Tlo1bko4N1lwXG5YV3hsM2RkSnRmV2RmTmgvSU1zZGhvSTBGMEhIMUIwdnBoOGl5L01kbDBsSExpeUNUdXVDS01PZ0NhNFRubENXXG5PcjJkaGJSSG5aV1ZtaXd4dVR4cllGRVRVeUZERDJiNVhjV3loQlh5ajJZNVpnVldqQWhmMlVyblJRTjJvMVVHXG44WVVBUzEwVEFnTUJBQUVDZ2dFQVF6MGJtYk14VnFrSGp5ZmxUVHZUS09wTkZPUGlBRVN0dlVvVmN4S2tIbDlZXG5WYUZSSkFBWnFUMERjL3BJUnFXYUtNeVN6WXd1ZC9CVWtvbFBWV0ZrT2NMTWlqYmtRWCt1c2NQQjl0b01hM3VoXG42ZU5HUDlvQnc4WDFacmJIbE9yREJpTXo0b21LVE9tQkNnM1puOWUzeGhRelBzYmd3UkNnN3d0NSs3NDl2MWRJXG5vVUh4MitXcDZ2d3ZQV0NVRDFHb0RDSElXWUthNG9kN2FvWmhnSDlhQm1ubkZ6dWYydXJuRTVuYUMzR1o3dUVsXG4zUCt0eVIvTlFLR2RZWm5yY3NTM1B6MWtoTFBMczFTL25kRk5MU1pOemVxMWpOajVRdWYxd05wdDBvYjJsZ1RGXG5jYmQrV2lOYWF5M0gvOW5DQXFJMzUzOUNQVlZpK0pNOEtPYlVYVjJ0WlFLQmdRRHdLeXM4bElJdFZSRE9yTHljXG4vaG1DdXZPdHJlUFR0TFB6MlFYZFZzNVhKanNEd3Z3MWJoeXc2VGN6UERNZXFSYUhQNUtCZW5kOEwwc3d4MjYxXG5HMGUyRXVGcnBSejk1VWNCNWFxSHkvcHp5MEtLQ0krbitIUURlUlNlSks2aytNdjJldzVpODhobUxtVTFVTW9QXG5kbDIraFBBWDRzL0dXTXQ2c3Vhb2kraXFKd0tCZ1FEc0ZxT1NHZmIvMGFXVzZwVSt0OWRxc21nRkV2R3NsQk9lXG5ZM0NLU3dlNDFhcW1ZcTRZaEp5bVg1dmtjWEl1SFlsVUtKdTNIOU9vbzBoeW12OHcxR2RwRHY5eDE1TUJQakd5XG5kOEZyeU1tK0FMVXpKaXgzSFJHcTl5VHd5cjdtaGE0Qm5kcmI4K0tTRk1hRFEzNWNkZ3JpUWgzdEdIOCsycWtrXG5TemMwWXdPbE5RS0JnR3UyNE1obHp0Q29FMGF1WUZXRS9Vb05zUmFYSTlRaWVvY0dNY1FvbDVpc2s5RkhGVGlkXG5idzdGT2pXbmJVSDJFaDJNbkplbnBva3k2T1V5dk90TEZlbUtKRUhVSnVHVWdEbFFtU0FZa3ZaMkZoeTBaRUd3XG5nOCsrOFVsUUtHZmpFZzgwOTZuWHJteHRxSVMxL0RuZEc0UkVPUzV0VWtTaU5IaU9YamIvc05VSEFvR0FFbzVJXG45dS9CZ1NQYUx2MXJFNDNoaVlwU01Ldm5nTmYybnNsVURCcVBsZEI5WkN4M1lJZnp4QVBadmQvSXlLVWJxUml6XG4vSFdzN2lFL1RYcXZPZ2hIeEhNZ1VyTk40NWdlMGRjbHhiSDNZVTZ1NzBFOTEzTGFjNlNQSzduVHZVeWVlNVFMXG5vcVFObDh1NE9wTHdlSlh5and3QlRDUlR3LzN0czJPU0NEVU1FVTBDZ1lCdW9ocGdMMUxGT2dXc3R6M1B5UUVtXG5POHdvRVFtelVINFU3SUx4U1VCVkJ5dnpqa1NZL2Z3NzVQc1NQMUl2eS9DYi9yQWRoRFI2MU9taVk5RWFJQXBmXG42YmN5cDAySElrNGhKb0IybTE4RmNYejQ5cGFPUncxb0I2bkVDTXg5Tk5jbGx4cFV4ak9SSk1idGxZV2Y3SUZ4XG5jTlQySDljQUdZVDZ2c2RsekJIOFd3PT1cbi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS1cbiIsCiAgImNsaWVudF9lbWFpbCI6ICJ0ZXN0LTg3MUBqb2UtdGVzdC1wcm9qZWN0LTM3MjQxOC5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsCiAgImNsaWVudF9pZCI6ICIxMTcwMDIxNjYzNjIzODM2MzMyMzMiLAogICJhdXRoX3VyaSI6ICJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20vby9vYXV0aDIvYXV0aCIsCiAgInRva2VuX3VyaSI6ICJodHRwczovL29hdXRoMi5nb29nbGVhcGlzLmNvbS90b2tlbiIsCiAgImF1dGhfcHJvdmlkZXJfeDUwOV9jZXJ0X3VybCI6ICJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9vYXV0aDIvdjEvY2VydHMiLAogICJjbGllbnRfeDUwOV9jZXJ0X3VybCI6ICJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9yb2JvdC92MS9tZXRhZGF0YS94NTA5L3Rlc3QtODcxJTQwam9lLXRlc3QtcHJvamVjdC0zNzI0MTguaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20iCn0="
}
`
}
// resource.Test(t, resource.TestCase{
// PreCheck: func() {
// if v := os.Getenv("SYSDIG_MONITOR_API_TOKEN"); v == "" {
// t.Fatal("SYSDIG_MONITOR_API_TOKEN must be set for acceptance tests")
// }
// },
// ProviderFactories: map[string]func() (*schema.Provider, error){
// "sysdig": func() (*schema.Provider, error) {
// return sysdig.Provider(), nil
// },
// },
// Steps: []resource.TestStep{
// {
// Config: monitorCustomerProviderKey(),
// ExpectNonEmptyPlan: true,
// },
// },
// })
// }

// func monitorCustomerProviderKey() string {
// return `
// resource "sysdig_monitor_cloud_account" "provider" {
// cloud_provider = "GCP"
// integration_type = "API"
// account_id = "joe-test-project-372418"
// additional_options = "ewogICJ0eXBlIjogInNlcnZpY2VfYWNjb3VudCIsCiAgInByb2plY3RfaWQiOiAiam9lLXRlc3QtcHJvamVjdC0zNzI0MTgiLAogICJwcml2YXRlX2tleV9pZCI6ICI2MzVlMTk0ZGNkODI4MWU5ZWE1YWZlMmJjNjdlMGIwYjY0OGI2YTM4IiwKICAicHJpdmF0ZV9rZXkiOiAiLS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tXG5NSUlFdkFJQkFEQU5CZ2txaGtpRzl3MEJBUUVGQUFTQ0JLWXdnZ1NpQWdFQUFvSUJBUURkZlFrR0haN3d5Z3RKXG5kVnlKVHM5M3g5SldMeXQ4bTh2cHZNYzVzUDltMzRBQ1k0bTNNMGNxcE8yZWVkRTlWSURIeVR0Z25RZ3Fja2ZNXG5KTDlFZE9HQURHOEJlcFh5WmdiWjR2c2NvdDB4emFTTDRkQ3pvVDJqUEkvV3JEdFFaSGR4K1hOc0VpZFFzYjlQXG5qTndnN29DSE5XSkY3MXRNZCt3dUphejFMTlJOME5sRnU3b01BV3N0KzluQjIwS2FLZDZpTWY3Tlo1bko4N1lwXG5YV3hsM2RkSnRmV2RmTmgvSU1zZGhvSTBGMEhIMUIwdnBoOGl5L01kbDBsSExpeUNUdXVDS01PZ0NhNFRubENXXG5PcjJkaGJSSG5aV1ZtaXd4dVR4cllGRVRVeUZERDJiNVhjV3loQlh5ajJZNVpnVldqQWhmMlVyblJRTjJvMVVHXG44WVVBUzEwVEFnTUJBQUVDZ2dFQVF6MGJtYk14VnFrSGp5ZmxUVHZUS09wTkZPUGlBRVN0dlVvVmN4S2tIbDlZXG5WYUZSSkFBWnFUMERjL3BJUnFXYUtNeVN6WXd1ZC9CVWtvbFBWV0ZrT2NMTWlqYmtRWCt1c2NQQjl0b01hM3VoXG42ZU5HUDlvQnc4WDFacmJIbE9yREJpTXo0b21LVE9tQkNnM1puOWUzeGhRelBzYmd3UkNnN3d0NSs3NDl2MWRJXG5vVUh4MitXcDZ2d3ZQV0NVRDFHb0RDSElXWUthNG9kN2FvWmhnSDlhQm1ubkZ6dWYydXJuRTVuYUMzR1o3dUVsXG4zUCt0eVIvTlFLR2RZWm5yY3NTM1B6MWtoTFBMczFTL25kRk5MU1pOemVxMWpOajVRdWYxd05wdDBvYjJsZ1RGXG5jYmQrV2lOYWF5M0gvOW5DQXFJMzUzOUNQVlZpK0pNOEtPYlVYVjJ0WlFLQmdRRHdLeXM4bElJdFZSRE9yTHljXG4vaG1DdXZPdHJlUFR0TFB6MlFYZFZzNVhKanNEd3Z3MWJoeXc2VGN6UERNZXFSYUhQNUtCZW5kOEwwc3d4MjYxXG5HMGUyRXVGcnBSejk1VWNCNWFxSHkvcHp5MEtLQ0krbitIUURlUlNlSks2aytNdjJldzVpODhobUxtVTFVTW9QXG5kbDIraFBBWDRzL0dXTXQ2c3Vhb2kraXFKd0tCZ1FEc0ZxT1NHZmIvMGFXVzZwVSt0OWRxc21nRkV2R3NsQk9lXG5ZM0NLU3dlNDFhcW1ZcTRZaEp5bVg1dmtjWEl1SFlsVUtKdTNIOU9vbzBoeW12OHcxR2RwRHY5eDE1TUJQakd5XG5kOEZyeU1tK0FMVXpKaXgzSFJHcTl5VHd5cjdtaGE0Qm5kcmI4K0tTRk1hRFEzNWNkZ3JpUWgzdEdIOCsycWtrXG5TemMwWXdPbE5RS0JnR3UyNE1obHp0Q29FMGF1WUZXRS9Vb05zUmFYSTlRaWVvY0dNY1FvbDVpc2s5RkhGVGlkXG5idzdGT2pXbmJVSDJFaDJNbkplbnBva3k2T1V5dk90TEZlbUtKRUhVSnVHVWdEbFFtU0FZa3ZaMkZoeTBaRUd3XG5nOCsrOFVsUUtHZmpFZzgwOTZuWHJteHRxSVMxL0RuZEc0UkVPUzV0VWtTaU5IaU9YamIvc05VSEFvR0FFbzVJXG45dS9CZ1NQYUx2MXJFNDNoaVlwU01Ldm5nTmYybnNsVURCcVBsZEI5WkN4M1lJZnp4QVBadmQvSXlLVWJxUml6XG4vSFdzN2lFL1RYcXZPZ2hIeEhNZ1VyTk40NWdlMGRjbHhiSDNZVTZ1NzBFOTEzTGFjNlNQSzduVHZVeWVlNVFMXG5vcVFObDh1NE9wTHdlSlh5and3QlRDUlR3LzN0czJPU0NEVU1FVTBDZ1lCdW9ocGdMMUxGT2dXc3R6M1B5UUVtXG5POHdvRVFtelVINFU3SUx4U1VCVkJ5dnpqa1NZL2Z3NzVQc1NQMUl2eS9DYi9yQWRoRFI2MU9taVk5RWFJQXBmXG42YmN5cDAySElrNGhKb0IybTE4RmNYejQ5cGFPUncxb0I2bkVDTXg5Tk5jbGx4cFV4ak9SSk1idGxZV2Y3SUZ4XG5jTlQySDljQUdZVDZ2c2RsekJIOFd3PT1cbi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS1cbiIsCiAgImNsaWVudF9lbWFpbCI6ICJ0ZXN0LTg3MUBqb2UtdGVzdC1wcm9qZWN0LTM3MjQxOC5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsCiAgImNsaWVudF9pZCI6ICIxMTcwMDIxNjYzNjIzODM2MzMyMzMiLAogICJhdXRoX3VyaSI6ICJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20vby9vYXV0aDIvYXV0aCIsCiAgInRva2VuX3VyaSI6ICJodHRwczovL29hdXRoMi5nb29nbGVhcGlzLmNvbS90b2tlbiIsCiAgImF1dGhfcHJvdmlkZXJfeDUwOV9jZXJ0X3VybCI6ICJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9vYXV0aDIvdjEvY2VydHMiLAogICJjbGllbnRfeDUwOV9jZXJ0X3VybCI6ICJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9yb2JvdC92MS9tZXRhZGF0YS94NTA5L3Rlc3QtODcxJTQwam9lLXRlc3QtcHJvamVjdC0zNzI0MTguaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20iCn0="
// }
// `
// }
Loading

0 comments on commit 922da70

Please sign in to comment.