Skip to content

gitops abac rules #119

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Jun 30, 2023
Merged
4 changes: 3 additions & 1 deletion client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type Client struct {
Token string
TokenHeader string
Host string
HostV2 string
Client *http.Client
}

Expand All @@ -29,12 +30,13 @@ type RequestOptions struct {
// NewClient returns a new client configured to communicate on a server with the
// given hostname and to send an Authorization Header with the value of
// token
func NewClient(hostname string, token string, tokenHeader string) *Client {
func NewClient(hostname string, hostnameV2 string, token string, tokenHeader string) *Client {
if tokenHeader == "" {
tokenHeader = "Authorization"
}
return &Client{
Host: hostname,
HostV2: hostnameV2,
Token: token,
TokenHeader: tokenHeader,
Client: &http.Client{},
Expand Down
206 changes: 206 additions & 0 deletions client/gitops_abac_rules.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
package client

import (
"fmt"
)

type EntityAbacAttribute struct {
Name string `json:"name"`
Key string `json:"key,omitempty"`
Value string `json:"value"`
}

// GitopsAbacRule spec
type GitopsAbacRule struct {
ID string `json:"id,omitempty"`
AccountId string `json:"accountId,omitempty"`
EntityType string `json:"entityType"`
Teams []string `json:"teams"`
Tags []string `json:"tags,omitempty"`
Actions []string `json:"actions"`
Attributes []EntityAbacAttribute `json:"attributes"`
}

type GitopsAbacRulesListResponse struct {
Data struct {
AbacRules []GitopsAbacRule `json:"abacRules"`
} `json:"data"`
}

type GitopsAbacRuleResponse struct {
Data struct {
AbacRule GitopsAbacRule `json:"abacRule,omitempty"`
CreateAbacRule GitopsAbacRule `json:"createAbacRule,omitempty"`
RemoveAbacRule GitopsAbacRule `json:"removeAbacRule,omitempty"`
} `json:"data"`
}

func (client *Client) GetAbacRulesList(entityType string) ([]GitopsAbacRule, error) {
request := GraphQLRequest{
Query: `
query AbacRules($accountId: String!, $entityType: AbacEntityValues!) {
abacRules(accountId: $accountId, entityType: $entityType) {
id
accountId
entityType
teams
tags
actions
attributes {
name
key
value
}
}
}
`,
Variables: map[string]interface{}{
"accountId": "",
"entityType": entityType,
},
}

response, err := client.SendGqlRequest(request)
if err != nil {
fmt.Println("Error:", err)
return nil, err
}

var gitopsAbacRulesResponse GitopsAbacRulesListResponse
err = DecodeGraphQLResponseInto(response, &gitopsAbacRulesResponse)
if err != nil {
return nil, err
}

return gitopsAbacRulesResponse.Data.AbacRules, nil
}

// GetAbacRuleByID -
func (client *Client) GetAbacRuleByID(id string) (*GitopsAbacRule, error) {
request := GraphQLRequest{
Query: `
query AbacRule($accountId: String!, $id: ID!) {
abacRule(accountId: $accountId, id: $id) {
id
accountId
entityType
teams
tags
actions
attributes {
name
key
value
}
}
}
`,
Variables: map[string]interface{}{
"accountId": "",
"id": id,
},
}

response, err := client.SendGqlRequest(request)
if err != nil {
fmt.Println("Error:", err)
return nil, err
}

var gitopsAbacRuleResponse GitopsAbacRuleResponse
err = DecodeGraphQLResponseInto(response, &gitopsAbacRuleResponse)
if err != nil {
return nil, err
}

return &gitopsAbacRuleResponse.Data.AbacRule, nil
}

func (client *Client) CreateAbacRule(gitopsAbacRule *GitopsAbacRule) (*GitopsAbacRule, error) {

newAbacRule := &GitopsAbacRule{
EntityType: gitopsAbacRule.EntityType,
Teams: gitopsAbacRule.Teams,
Tags: gitopsAbacRule.Tags,
Actions: gitopsAbacRule.Actions,
Attributes: gitopsAbacRule.Attributes,
}

request := GraphQLRequest{
Query: `
mutation CreateAbacRule($accountId: String!, $createAbacRuleInput: CreateAbacRuleInput!) {
createAbacRule(accountId: $accountId, createAbacRuleInput: $createAbacRuleInput) {
id
accountId
entityType
teams
tags
actions
attributes {
name
key
value
}
}
}
`,
Variables: map[string]interface{}{
"accountId": "",
"createAbacRuleInput": newAbacRule,
},
}

response, err := client.SendGqlRequest(request)
if err != nil {
fmt.Println("Error:", err)
return nil, err
}

var gitopsAbacRuleResponse GitopsAbacRuleResponse
err = DecodeGraphQLResponseInto(response, &gitopsAbacRuleResponse)
if err != nil {
return nil, err
}

return &gitopsAbacRuleResponse.Data.CreateAbacRule, nil
}

func (client *Client) DeleteAbacRule(id string) (*GitopsAbacRule, error) {
request := GraphQLRequest{
Query: `
mutation RemoveAbacRule($accountId: String!, $id: ID!) {
removeAbacRule(accountId: $accountId, id: $id) {
id
accountId
entityType
teams
tags
actions
attributes {
name
key
value
}
}
}
`,
Variables: map[string]interface{}{
"accountId": "",
"id": id,
},
}

response, err := client.SendGqlRequest(request)
if err != nil {
fmt.Println("Error:", err)
return nil, err
}

var gitopsAbacRuleResponse GitopsAbacRuleResponse
err = DecodeGraphQLResponseInto(response, &gitopsAbacRuleResponse)
if err != nil {
return nil, err
}

return &gitopsAbacRuleResponse.Data.RemoveAbacRule, nil
}
57 changes: 57 additions & 0 deletions client/gql_client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package client

import (
"bytes"
"encoding/json"
"errors"
"io/ioutil"
"net/http"
)

// GraphQLRequest GraphQL query
type GraphQLRequest struct {
Query string `json:"query"`
Variables map[string]interface{} `json:"variables,omitempty"`
}

func (client *Client) SendGqlRequest(request GraphQLRequest) ([]byte, error) {
jsonRequest, err := json.Marshal(request)
if err != nil {
return nil, err
}

req, err := http.NewRequest("POST", client.HostV2, bytes.NewBuffer(jsonRequest))
if err != nil {
return nil, err
}

tokenHeader := client.TokenHeader
if tokenHeader == "" {
tokenHeader = "Authorization"
}
req.Header.Set(tokenHeader, client.Token)
req.Header.Set("Content-Type", "application/json; charset=utf-8")

httpClient := &http.Client{}
resp, err := httpClient.Do(req)
if err != nil {
return nil, err
}
if resp.StatusCode >= 400 {
bodyBytes, _ := ioutil.ReadAll(resp.Body)
return nil, errors.New(resp.Status + " " + string(bodyBytes))
}
defer resp.Body.Close()

var buf bytes.Buffer
_, err = buf.ReadFrom(resp.Body)
if err != nil {
return nil, err
}

return buf.Bytes(), nil
}

func DecodeGraphQLResponseInto(body []byte, target interface{}) error {
return json.Unmarshal(body, target)
}
2 changes: 1 addition & 1 deletion client/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ func (client *Client) AddUserToTeamByAdmin(userID string, accountID string, team
return err
}
// new Client for accountAdmin
accountAdminClient := NewClient(client.Host, accountAdminToken, "x-access-token")
accountAdminClient := NewClient(client.Host, "", accountAdminToken, "x-access-token")
usersTeam, err := accountAdminClient.GetTeamByName(team)
if err != nil {
return err
Expand Down
2 changes: 2 additions & 0 deletions codefresh/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ const (
ENV_CODEFRESH_PLUGIN_DEBUG = "CODEFRESH_PLUGIN_DEBUG"
ENV_CODEFRESH_PLUGIN_ADDR = "CODEFRESH_PLUGIN_ADDR"
ENV_CODEFRESH_API_URL = "CODEFRESH_API_URL"
ENV_CODEFRESH_API2_URL = "CODEFRESH_API2_URL"
ENV_CODEFRESH_API_KEY = "CODEFRESH_API_KEY"
DEFAULT_CODEFRESH_API_URL = "https://g.codefresh.io/api"
DEFAULT_CODEFRESH_API2_URL = "https://g.codefresh.io/2.0/api/graphql"
DEFAULT_CODEFRESH_PLUGIN_ADDR = "registry.terraform.io/-/codefresh"
)
15 changes: 14 additions & 1 deletion codefresh/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,17 @@ func Provider() *schema.Provider {
},
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),
},
"api_url_v2": {
Type: schema.TypeString,
Optional: true,
DefaultFunc: func() (interface{}, error) {
if url := os.Getenv(ENV_CODEFRESH_API2_URL); url != "" {
return url, nil
}
return DEFAULT_CODEFRESH_API2_URL, nil
},
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),
},
"token": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -55,6 +66,7 @@ func Provider() *schema.Provider {
"codefresh_step_types": resourceStepTypes(),
"codefresh_user": resourceUser(),
"codefresh_team": resourceTeam(),
"codefresh_abac_rules": resourceGitopsAbacRule(),
},
ConfigureFunc: configureProvider,
}
Expand All @@ -63,9 +75,10 @@ func Provider() *schema.Provider {
func configureProvider(d *schema.ResourceData) (interface{}, error) {

apiURL := d.Get("api_url").(string)
apiURLV2 := d.Get("api_url_v2").(string)
token := d.Get("token").(string)
if token == "" {
token = os.Getenv(ENV_CODEFRESH_API_KEY)
}
return cfClient.NewClient(apiURL, token, ""), nil
return cfClient.NewClient(apiURL, apiURLV2, token, ""), nil
}
Loading