Skip to content
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

feat: infiscial-project-group resource #52

Merged
merged 20 commits into from
Sep 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
0a5d037
feat: base implementation of infiscial-project-group resource
sheensantoscapadngan Sep 13, 2024
8841794
misc: finished up integration
sheensantoscapadngan Sep 15, 2024
0881989
misc: finalized configuration and docs
sheensantoscapadngan Sep 15, 2024
1c9d6ac
Merge remote-tracking branch 'origin/main' into feat/infisical-projec…
sheensantoscapadngan Sep 15, 2024
65a28e5
misc: addressed lint issues
sheensantoscapadngan Sep 15, 2024
95780dc
misc: added note
sheensantoscapadngan Sep 15, 2024
5d374af
misc: addressed issue with role ordering and simplified logic
sheensantoscapadngan Sep 17, 2024
ed2f359
misc: updated documentation
sheensantoscapadngan Sep 17, 2024
00b977d
misc: added handling of infisical-side updates
sheensantoscapadngan Sep 17, 2024
67e7037
misc: addressed infinite drift
sheensantoscapadngan Sep 18, 2024
709227f
misc: updated comment
sheensantoscapadngan Sep 18, 2024
5704ce6
misc: updated doc
sheensantoscapadngan Sep 18, 2024
e95bcb2
misc: made temporary access start date required for temporary roles
sheensantoscapadngan Sep 19, 2024
ccbe262
misc: improved error log
sheensantoscapadngan Sep 19, 2024
691d55e
misc: added example values
sheensantoscapadngan Sep 19, 2024
76631f2
misc: added more example values for temporary_access_start_time
sheensantoscapadngan Sep 19, 2024
acf379c
misc: moved towards usage of ID
sheensantoscapadngan Sep 20, 2024
4496b97
misc: added groups data source
sheensantoscapadngan Sep 20, 2024
53e376a
misc: moved to project group v3 get
sheensantoscapadngan Sep 22, 2024
0518fd3
misc: moved rest of resource methods to use IDs
sheensantoscapadngan Sep 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions docs/data-sources/groups.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "infisical_groups Data Source - terraform-provider-infisical"
subcategory: ""
description: |-
Interact with Infisical groups in your organization.
---

# infisical_groups (Data Source)

Interact with Infisical groups in your organization.

## Example Usage

```terraform
terraform {
required_providers {
infisical = {
# version = <latest version>
source = "infisical/infisical"
}
}
}

provider "infisical" {
host = "https://app.infisical.com" # Only required if using self hosted instance of Infisical, default is https://app.infisical.com
client_id = "<>"
client_secret = "<>"
}


data "infisical_groups" "groups" {

}

output "org-groups" {
value = data.infisical_groups.groups
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Read-Only

- `groups` (Attributes List) The groups list (see [below for nested schema](#nestedatt--groups))

<a id="nestedatt--groups"></a>
### Nested Schema for `groups`

Read-Only:

- `id` (String) The ID of the group
- `name` (String) The name of the group
- `org_id` (String) The organization ID of the group
- `role` (String) The role of the group in the organization
- `role_id` (String) The role ID of the group in the organization
77 changes: 77 additions & 0 deletions docs/resources/project_group.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "infisical_project_group Resource - terraform-provider-infisical"
subcategory: ""
description: |-
Create project groups & save to Infisical. Only Machine Identity authentication is supported for this data source
---

# infisical_project_group (Resource)

Create project groups & save to Infisical. Only Machine Identity authentication is supported for this data source

## Example Usage

```terraform
terraform {
required_providers {
infisical = {
# version = <latest version>
source = "infisical/infisical"
}
}
}

provider "infisical" {
host = "https://app.infisical.com" # Only required if using self hosted instance of Infisical, default is https://app.infisical.com
client_id = "<>"
client_secret = "<>"
}

resource "infisical_project" "example" {
name = "example"
slug = "example"
}

resource "infisical_project_group" "group" {
project_id = infisical_project.example.id
group_slug = "my-group"
roles = [
{
role_slug = "admin",
is_temporary = true,
temporary_access_start_time = "2024-09-19T12:43:13Z",
temporary_range = "1y"
},
{
role_slug = "my-custom-role",
},
]
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `group_id` (String) The id of the group.
- `project_id` (String) The id of the project.
- `roles` (Attributes Set) The roles assigned to the project group (see [below for nested schema](#nestedatt--roles))

### Read-Only

- `membership_id` (String) The membership Id of the project group

<a id="nestedatt--roles"></a>
### Nested Schema for `roles`

Required:

- `role_slug` (String) The slug of the role

Optional:

- `is_temporary` (Boolean) Flag to indicate the assigned role is temporary or not. When is_temporary is true fields temporary_mode, temporary_range and temporary_access_start_time is required.
- `temporary_access_start_time` (String) ISO time for which temporary access should begin. This is in the format YYYY-MM-DDTHH:MM:SSZ e.g. 2024-09-19T12:43:13Z
- `temporary_range` (String) TTL for the temporary time. Eg: 1m, 1h, 1d. Default: 1h
23 changes: 23 additions & 0 deletions examples/data-sources/infisical_groups/data-source.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
terraform {
required_providers {
infisical = {
# version = <latest version>
source = "infisical/infisical"
}
}
}

provider "infisical" {
host = "https://app.infisical.com" # Only required if using self hosted instance of Infisical, default is https://app.infisical.com
client_id = "<>"
client_secret = "<>"
}


data "infisical_groups" "groups" {

}

output "org-groups" {
value = data.infisical_groups.groups
}
35 changes: 35 additions & 0 deletions examples/resources/infisical_project_group/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
terraform {
required_providers {
infisical = {
# version = <latest version>
source = "infisical/infisical"
}
}
}

provider "infisical" {
host = "https://app.infisical.com" # Only required if using self hosted instance of Infisical, default is https://app.infisical.com
client_id = "<>"
client_secret = "<>"
}

resource "infisical_project" "example" {
name = "example"
slug = "example"
}

resource "infisical_project_group" "group" {
project_id = infisical_project.example.id
group_slug = "my-group"
roles = [
{
role_slug = "admin",
is_temporary = true,
temporary_access_start_time = "2024-09-19T12:43:13Z",
temporary_range = "1y"
},
{
role_slug = "my-custom-role",
},
]
}
50 changes: 50 additions & 0 deletions internal/client/group.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package infisicalclient

import (
"fmt"
"net/http"
)

func (client Client) GetGroupById(request GetGroupByIdRequest) (Group, error) {
var groupResponse Group
response, err := client.Config.HttpClient.
R().
SetResult(&groupResponse).
SetHeader("User-Agent", USER_AGENT).
Get(fmt.Sprintf("api/v1/groups/%s", request.ID))

if response.StatusCode() == http.StatusNotFound {
return Group{}, ErrNotFound
}

if err != nil {
return Group{}, fmt.Errorf("CallGetGroupById: Unable to complete api request [err=%s]", err)
}

if response.IsError() {
return Group{}, fmt.Errorf("CallGetGroupById: Unsuccessful response. [response=%s]", response)
}

return groupResponse, nil
}

func (client Client) GetGroups() (GetGroupsResponse, error) {
var body GetGroupsResponse

httpRequest := client.Config.HttpClient.
R().
SetResult(&body).
SetHeader("User-Agent", USER_AGENT)

response, err := httpRequest.Get("api/v1/groups")

if err != nil {
return GetGroupsResponse{}, fmt.Errorf("GetGroups: Unable to complete api request [err=%s]", err)
}

if response.IsError() {
return GetGroupsResponse{}, fmt.Errorf("GetGroups: Unsuccessful response. [response=%v]", string(response.Body()))
}

return body, nil
}
118 changes: 118 additions & 0 deletions internal/client/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,10 @@ type ProjectWithEnvironments struct {
Environments []ProjectEnvironment `json:"environments"`
}

type GetProjectByIdResponse struct {
Workspace ProjectWithEnvironments `json:"workspace"`
}

type ProjectMemberships struct {
ID string `json:"id"`
CreatedAt time.Time `json:"createdAt"`
Expand Down Expand Up @@ -510,6 +514,10 @@ type GetProjectRequest struct {
Slug string `json:"slug"`
}

type GetProjectByIdRequest struct {
ID string `json:"id"`
}

type UpdateProjectRequest struct {
Slug string `json:"slug"`
ProjectName string `json:"name"`
Expand Down Expand Up @@ -780,6 +788,116 @@ type GetProjectIdentitySpecificPrivilegeResponse struct {
Privilege ProjectIdentitySpecificPrivilege `json:"privilege"`
}

type ProjectGroupRole struct {
ID string `json:"id"`
Role string `json:"role"`
CustomRoleSlug string `json:"customRoleSlug"`
CustomRoleId string `json:"customRoleId"`
IsTemporary bool `json:"isTemporary"`
TemporaryMode string `json:"temporaryMode"`
TemporaryRange string `json:"temporaryRange"`
TemporaryAccessStartTime time.Time `json:"temporaryAccessStartTime"`
TemporaryAccessEndTime time.Time `json:"temporaryAccessEndTime"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}

type ProjectGroup struct {
ID string `json:"id"`
GroupID string `json:"groupId"`
Roles []ProjectGroupRole
}

type CreateProjectGroupRequestRoles struct {
Role string `json:"role"`
IsTemporary bool `json:"isTemporary"`
TemporaryMode string `json:"temporaryMode"`
TemporaryRange string `json:"temporaryRange"`
TemporaryAccessStartTime time.Time `json:"temporaryAccessStartTime"`
}

type CreateProjectGroupRequest struct {
ProjectId string `json:"projectId"`
GroupId string `json:"groupId"`
Roles []CreateProjectGroupRequestRoles `json:"roles"`
}

type CreateProjectGroupResponseMembers struct {
ID string `json:"id"`
GroupID string `json:"groupId"`
}

type CreateProjectGroupResponse struct {
Membership CreateProjectGroupResponseMembers `json:"groupMembership"`
}

type GetProjectGroupMembershipRequest struct {
ProjectId string `json:"projectId"`
GroupId string `json:"groupId"`
}

type GetProjectGroupMembershipResponse struct {
Membership ProjectGroup `json:"groupMembership"`
}

type UpdateProjectGroupRequestRoles struct {
Role string `json:"role"`
IsTemporary bool `json:"isTemporary"`
TemporaryMode string `json:"temporaryMode"`
TemporaryRange string `json:"temporaryRange"`
TemporaryAccessStartTime time.Time `json:"temporaryAccessStartTime"`
}

type UpdateProjectGroupRequest struct {
ProjectId string `json:"projectId"`
GroupId string `json:"groupId"`
Roles []UpdateProjectGroupRequestRoles `json:"roles"`
}

type UpdateProjectGroupResponse struct {
Roles []struct {
ID string `json:"id"`
Role string `json:"role"`
CustomRoleId string `json:"customRoleId"`
IsTemporary bool `json:"isTemporary"`
TemporaryMode string `json:"temporaryMode"`
TemporaryRange string `json:"temporaryRange"`
TemporaryAccessStartTime time.Time `json:"temporaryAccessStartTime"`
TemporaryAccessEndTime time.Time `json:"temporaryAccessEndTime"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
} `json:"roles"`
}

type DeleteProjectGroupRequest struct {
ProjectId string `json:"projectId"`
GroupId string `json:"groupId"`
}

type DeleteProjectGroupResponseMembers struct {
ID string `json:"id"`
GroupID string `json:"groupId"`
}

type DeleteProjectGroupResponse struct {
Membership DeleteProjectGroupResponseMembers `json:"groupMembership"`
}

type GetGroupByIdRequest struct {
ID string `json:"id"`
}

type Group struct {
ID string `json:"id"`
OrgID string `json:"orgId"`
Name string `json:"name"`
Slug string `json:"slug"`
Role string `json:"role"`
RoleId string `json:"roleId"`
}

type GetGroupsResponse []Group

type GetProjectTagsResponse struct {
Tags []ProjectTag `json:"workspaceTags"`
}
Expand Down
Loading
Loading