Skip to content

Commit ab97b85

Browse files
gitops abac rules (#119)
## What - Add Gitops ABAC Rule resource ## Why For creating rules for gitops entities ## Notes ## Checklist * [x] _I have read [CONTRIBUTING.md](https://github.com/codefresh-io/terraform-provider-codefresh/blob/master/CONTRIBUTING.md)._ * [x] _I have [allowed changes to my fork to be made](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork)._ * [x] _I have added tests, assuming new tests are warranted_. * [x] _I understand that the `/test` comment will be ignored by the CI trigger [unless it is made by a repo admin or collaborator](https://codefresh.io/docs/docs/pipelines/triggers/git-triggers/#support-for-building-pull-requests-from-forks)._
1 parent 2038cd8 commit ab97b85

18 files changed

+832
-4
lines changed

client/client.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ type Client struct {
1414
Token string
1515
TokenHeader string
1616
Host string
17+
HostV2 string
1718
Client *http.Client
1819
}
1920

@@ -29,12 +30,13 @@ type RequestOptions struct {
2930
// NewClient returns a new client configured to communicate on a server with the
3031
// given hostname and to send an Authorization Header with the value of
3132
// token
32-
func NewClient(hostname string, token string, tokenHeader string) *Client {
33+
func NewClient(hostname string, hostnameV2 string, token string, tokenHeader string) *Client {
3334
if tokenHeader == "" {
3435
tokenHeader = "Authorization"
3536
}
3637
return &Client{
3738
Host: hostname,
39+
HostV2: hostnameV2,
3840
Token: token,
3941
TokenHeader: tokenHeader,
4042
Client: &http.Client{},

client/gitops_abac_rules.go

+206
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
package client
2+
3+
import (
4+
"fmt"
5+
)
6+
7+
type EntityAbacAttribute struct {
8+
Name string `json:"name"`
9+
Key string `json:"key,omitempty"`
10+
Value string `json:"value"`
11+
}
12+
13+
// GitopsAbacRule spec
14+
type GitopsAbacRule struct {
15+
ID string `json:"id,omitempty"`
16+
AccountId string `json:"accountId,omitempty"`
17+
EntityType string `json:"entityType"`
18+
Teams []string `json:"teams"`
19+
Tags []string `json:"tags,omitempty"`
20+
Actions []string `json:"actions"`
21+
Attributes []EntityAbacAttribute `json:"attributes"`
22+
}
23+
24+
type GitopsAbacRulesListResponse struct {
25+
Data struct {
26+
AbacRules []GitopsAbacRule `json:"abacRules"`
27+
} `json:"data"`
28+
}
29+
30+
type GitopsAbacRuleResponse struct {
31+
Data struct {
32+
AbacRule GitopsAbacRule `json:"abacRule,omitempty"`
33+
CreateAbacRule GitopsAbacRule `json:"createAbacRule,omitempty"`
34+
RemoveAbacRule GitopsAbacRule `json:"removeAbacRule,omitempty"`
35+
} `json:"data"`
36+
}
37+
38+
func (client *Client) GetAbacRulesList(entityType string) ([]GitopsAbacRule, error) {
39+
request := GraphQLRequest{
40+
Query: `
41+
query AbacRules($accountId: String!, $entityType: AbacEntityValues!) {
42+
abacRules(accountId: $accountId, entityType: $entityType) {
43+
id
44+
accountId
45+
entityType
46+
teams
47+
tags
48+
actions
49+
attributes {
50+
name
51+
key
52+
value
53+
}
54+
}
55+
}
56+
`,
57+
Variables: map[string]interface{}{
58+
"accountId": "",
59+
"entityType": entityType,
60+
},
61+
}
62+
63+
response, err := client.SendGqlRequest(request)
64+
if err != nil {
65+
fmt.Println("Error:", err)
66+
return nil, err
67+
}
68+
69+
var gitopsAbacRulesResponse GitopsAbacRulesListResponse
70+
err = DecodeGraphQLResponseInto(response, &gitopsAbacRulesResponse)
71+
if err != nil {
72+
return nil, err
73+
}
74+
75+
return gitopsAbacRulesResponse.Data.AbacRules, nil
76+
}
77+
78+
// GetAbacRuleByID -
79+
func (client *Client) GetAbacRuleByID(id string) (*GitopsAbacRule, error) {
80+
request := GraphQLRequest{
81+
Query: `
82+
query AbacRule($accountId: String!, $id: ID!) {
83+
abacRule(accountId: $accountId, id: $id) {
84+
id
85+
accountId
86+
entityType
87+
teams
88+
tags
89+
actions
90+
attributes {
91+
name
92+
key
93+
value
94+
}
95+
}
96+
}
97+
`,
98+
Variables: map[string]interface{}{
99+
"accountId": "",
100+
"id": id,
101+
},
102+
}
103+
104+
response, err := client.SendGqlRequest(request)
105+
if err != nil {
106+
fmt.Println("Error:", err)
107+
return nil, err
108+
}
109+
110+
var gitopsAbacRuleResponse GitopsAbacRuleResponse
111+
err = DecodeGraphQLResponseInto(response, &gitopsAbacRuleResponse)
112+
if err != nil {
113+
return nil, err
114+
}
115+
116+
return &gitopsAbacRuleResponse.Data.AbacRule, nil
117+
}
118+
119+
func (client *Client) CreateAbacRule(gitopsAbacRule *GitopsAbacRule) (*GitopsAbacRule, error) {
120+
121+
newAbacRule := &GitopsAbacRule{
122+
EntityType: gitopsAbacRule.EntityType,
123+
Teams: gitopsAbacRule.Teams,
124+
Tags: gitopsAbacRule.Tags,
125+
Actions: gitopsAbacRule.Actions,
126+
Attributes: gitopsAbacRule.Attributes,
127+
}
128+
129+
request := GraphQLRequest{
130+
Query: `
131+
mutation CreateAbacRule($accountId: String!, $createAbacRuleInput: CreateAbacRuleInput!) {
132+
createAbacRule(accountId: $accountId, createAbacRuleInput: $createAbacRuleInput) {
133+
id
134+
accountId
135+
entityType
136+
teams
137+
tags
138+
actions
139+
attributes {
140+
name
141+
key
142+
value
143+
}
144+
}
145+
}
146+
`,
147+
Variables: map[string]interface{}{
148+
"accountId": "",
149+
"createAbacRuleInput": newAbacRule,
150+
},
151+
}
152+
153+
response, err := client.SendGqlRequest(request)
154+
if err != nil {
155+
fmt.Println("Error:", err)
156+
return nil, err
157+
}
158+
159+
var gitopsAbacRuleResponse GitopsAbacRuleResponse
160+
err = DecodeGraphQLResponseInto(response, &gitopsAbacRuleResponse)
161+
if err != nil {
162+
return nil, err
163+
}
164+
165+
return &gitopsAbacRuleResponse.Data.CreateAbacRule, nil
166+
}
167+
168+
func (client *Client) DeleteAbacRule(id string) (*GitopsAbacRule, error) {
169+
request := GraphQLRequest{
170+
Query: `
171+
mutation RemoveAbacRule($accountId: String!, $id: ID!) {
172+
removeAbacRule(accountId: $accountId, id: $id) {
173+
id
174+
accountId
175+
entityType
176+
teams
177+
tags
178+
actions
179+
attributes {
180+
name
181+
key
182+
value
183+
}
184+
}
185+
}
186+
`,
187+
Variables: map[string]interface{}{
188+
"accountId": "",
189+
"id": id,
190+
},
191+
}
192+
193+
response, err := client.SendGqlRequest(request)
194+
if err != nil {
195+
fmt.Println("Error:", err)
196+
return nil, err
197+
}
198+
199+
var gitopsAbacRuleResponse GitopsAbacRuleResponse
200+
err = DecodeGraphQLResponseInto(response, &gitopsAbacRuleResponse)
201+
if err != nil {
202+
return nil, err
203+
}
204+
205+
return &gitopsAbacRuleResponse.Data.RemoveAbacRule, nil
206+
}

client/gql_client.go

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package client
2+
3+
import (
4+
"bytes"
5+
"encoding/json"
6+
"errors"
7+
"io/ioutil"
8+
"net/http"
9+
)
10+
11+
// GraphQLRequest GraphQL query
12+
type GraphQLRequest struct {
13+
Query string `json:"query"`
14+
Variables map[string]interface{} `json:"variables,omitempty"`
15+
}
16+
17+
func (client *Client) SendGqlRequest(request GraphQLRequest) ([]byte, error) {
18+
jsonRequest, err := json.Marshal(request)
19+
if err != nil {
20+
return nil, err
21+
}
22+
23+
req, err := http.NewRequest("POST", client.HostV2, bytes.NewBuffer(jsonRequest))
24+
if err != nil {
25+
return nil, err
26+
}
27+
28+
tokenHeader := client.TokenHeader
29+
if tokenHeader == "" {
30+
tokenHeader = "Authorization"
31+
}
32+
req.Header.Set(tokenHeader, client.Token)
33+
req.Header.Set("Content-Type", "application/json; charset=utf-8")
34+
35+
httpClient := &http.Client{}
36+
resp, err := httpClient.Do(req)
37+
if err != nil {
38+
return nil, err
39+
}
40+
if resp.StatusCode >= 400 {
41+
bodyBytes, _ := ioutil.ReadAll(resp.Body)
42+
return nil, errors.New(resp.Status + " " + string(bodyBytes))
43+
}
44+
defer resp.Body.Close()
45+
46+
var buf bytes.Buffer
47+
_, err = buf.ReadFrom(resp.Body)
48+
if err != nil {
49+
return nil, err
50+
}
51+
52+
return buf.Bytes(), nil
53+
}
54+
55+
func DecodeGraphQLResponseInto(body []byte, target interface{}) error {
56+
return json.Unmarshal(body, target)
57+
}

client/user.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ func (client *Client) AddUserToTeamByAdmin(userID string, accountID string, team
134134
return err
135135
}
136136
// new Client for accountAdmin
137-
accountAdminClient := NewClient(client.Host, accountAdminToken, "x-access-token")
137+
accountAdminClient := NewClient(client.Host, "", accountAdminToken, "x-access-token")
138138
usersTeam, err := accountAdminClient.GetTeamByName(team)
139139
if err != nil {
140140
return err

codefresh/env.go

+2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ const (
44
ENV_CODEFRESH_PLUGIN_DEBUG = "CODEFRESH_PLUGIN_DEBUG"
55
ENV_CODEFRESH_PLUGIN_ADDR = "CODEFRESH_PLUGIN_ADDR"
66
ENV_CODEFRESH_API_URL = "CODEFRESH_API_URL"
7+
ENV_CODEFRESH_API2_URL = "CODEFRESH_API2_URL"
78
ENV_CODEFRESH_API_KEY = "CODEFRESH_API_KEY"
89
DEFAULT_CODEFRESH_API_URL = "https://g.codefresh.io/api"
10+
DEFAULT_CODEFRESH_API2_URL = "https://g.codefresh.io/2.0/api/graphql"
911
DEFAULT_CODEFRESH_PLUGIN_ADDR = "registry.terraform.io/-/codefresh"
1012
)

codefresh/provider.go

+14-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,17 @@ func Provider() *schema.Provider {
2323
},
2424
Description: fmt.Sprintf("The Codefresh API URL. Defaults to `%s`. Can also be set using the `%s` environment variable.", DEFAULT_CODEFRESH_API_URL, ENV_CODEFRESH_API_URL),
2525
},
26+
"api_url_v2": {
27+
Type: schema.TypeString,
28+
Optional: true,
29+
DefaultFunc: func() (interface{}, error) {
30+
if url := os.Getenv(ENV_CODEFRESH_API2_URL); url != "" {
31+
return url, nil
32+
}
33+
return DEFAULT_CODEFRESH_API2_URL, nil
34+
},
35+
Description: fmt.Sprintf("The Codefresh gitops API URL. Defaults to `%s`. Can also be set using the `%s` environment variable.", DEFAULT_CODEFRESH_API2_URL, ENV_CODEFRESH_API2_URL),
36+
},
2637
"token": {
2738
Type: schema.TypeString,
2839
Optional: true,
@@ -55,6 +66,7 @@ func Provider() *schema.Provider {
5566
"codefresh_step_types": resourceStepTypes(),
5667
"codefresh_user": resourceUser(),
5768
"codefresh_team": resourceTeam(),
69+
"codefresh_abac_rules": resourceGitopsAbacRule(),
5870
},
5971
ConfigureFunc: configureProvider,
6072
}
@@ -63,9 +75,10 @@ func Provider() *schema.Provider {
6375
func configureProvider(d *schema.ResourceData) (interface{}, error) {
6476

6577
apiURL := d.Get("api_url").(string)
78+
apiURLV2 := d.Get("api_url_v2").(string)
6679
token := d.Get("token").(string)
6780
if token == "" {
6881
token = os.Getenv(ENV_CODEFRESH_API_KEY)
6982
}
70-
return cfClient.NewClient(apiURL, token, ""), nil
83+
return cfClient.NewClient(apiURL, apiURLV2, token, ""), nil
7184
}

0 commit comments

Comments
 (0)