Skip to content

Commit

Permalink
Implement methods for user secrets management
Browse files Browse the repository at this point in the history
This commit introduces internal/juju/userSecret and adds method to add user secrets.

Implement internal Juju secrets add, update, and remove functionality

This commit introduces several changes to the Juju client in the `internal/juju/client.go` file.
It includes the implementation of methods for adding, updating, and removing secrets. Additionally,

Furthermore, the commit includes changes to the `secret.go` file, introducing new types for managinng secrets.
It also includes changes to the `interfaces.go` file, defining new interfaces for the Juju client API.

Add secretURI to UpdateSecret

Add secretURI to DeleteSecret

Add AutoPrunt to UpdateSecret schema

Add SecretId to ReadSecret func instead of name.

Add lost Asserts.

Add secretNotFoundError

Extract mocks creation into separate suite.

Introduce typedError(err) usage in ClientAPI funcs.

Add renaming to UpdateSecret

Use struct raather than pointer for Output structures.

Introcue NewName in Update input struct.

Use pointers in all places in structs where the parameter is not
neccessary.

Implement schema for user secrets management

This commit introduces the ability to add, update, and remove user secrets in the schema.
This is done through the `userSecretResource` struct, which has methods for each of these actions.
The `Add`, `Update`, and `Remove` methods are currently stubbed out and will need to be implemented in future commits.

Add ReadSecret function implementation.

Implement Delete secret function

Add base64 encoding co Create and change Read fucntion to get value with
decode.

Add base64 encoding for values in Update
  • Loading branch information
anvial committed Apr 19, 2024
1 parent 83a987b commit 2769399
Show file tree
Hide file tree
Showing 22 changed files with 650 additions and 31 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,4 @@ grep "@module=juju.datasource" ./terraform.log
To find logs specific to the juju client talking to juju itself:
```shell
grep "@module=juju.client" ./terraform.log
```
```
1 change: 1 addition & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ Define the Juju controller credentials in the provider definition via environmen

```shell
export CONTROLLER=$(juju whoami | yq .Controller)
export JUJU_AGENT_VERSION="$(juju show-controller | yq '.[$CONTROLLER]'.details.\"agent-version\"|tr -d '"')"
export JUJU_CONTROLLER_ADDRESSES="$(juju show-controller | yq '.[$CONTROLLER]'.details.\"api-endpoints\" | tr -d "[]' "|tr -d '"'|tr -d '\n')"
export JUJU_USERNAME="$(cat ~/.local/share/juju/accounts.yaml | yq .controllers.$CONTROLLER.user|tr -d '"')"
export JUJU_PASSWORD="$(cat ~/.local/share/juju/accounts.yaml | yq .controllers.$CONTROLLER.password|tr -d '"')"
Expand Down
59 changes: 59 additions & 0 deletions docs/resources/secret.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "juju_secret Resource - terraform-provider-juju"
subcategory: ""
description: |-
A resource that represents a Juju secret.
---

# juju_secret (Resource)

A resource that represents a Juju secret.

## Example Usage

```terraform
resource "juju_secret" "this" {
model = juju_model.development.name
name = "this_secret_name"
value = {
key1 = "value1"
key2 = "value2"
}
info = "This is the secret"
}
```

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

### Required

- `model` (String) The model in which the secret belongs.
- `value` (Map of String, Sensitive) The value map of the secret. There can be more than one key-value pair.

### Optional

- `info` (String) The description of the secret.
- `name` (String) The name of the secret.

### Read-Only

- `secret_id` (String) The ID of the secret.

## Import

Import is supported using the following syntax:

```shell
# Secrets can be imported by using the URI as in the juju show-secrets output.
# Example:
# $juju show-secret secret-name
# coh2uo2ji6m0ue9a7tj0:
# revision: 1
# owner: <model>
# name: secret-name
# created: 2024-04-19T08:46:25Z
# updated: 2024-04-19T08:46:25Z
$ terraform import juju_secret.secret-name coh2uo2ji6m0ue9a7tj0
```
49 changes: 49 additions & 0 deletions docs/resources/secret_access.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "juju_secret_access Resource - terraform-provider-juju"
subcategory: ""
description: |-
A resource that represents a Juju secret access.
---

# juju_secret_access (Resource)

A resource that represents a Juju secret access.

## Example Usage

```terraform
resource "juju_secret_access" "this" {
model = juju_model.development.name
applications = [
juju_application.app.name, juju_application.app2.name
]
secret_id = juju_secret.that.secret_id
}
```

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

### Required

- `applications` (List of String) The list of applications to which the secret is granted or revoked.
- `model` (String) The model in which the secret belongs.
- `secret_id` (String) The ID of the secret.

## Import

Import is supported using the following syntax:

```shell
# Secret access can be imported by using the URI as in the juju show-secrets output.
# Example:
# $juju show-secret secret-name
# coh2uo2ji6m0ue9a7tj0:
# revision: 1
# owner: <model>
# name: secret-name
# created: 2024-04-19T08:46:25Z
# updated: 2024-04-19T08:46:25Z
$ terraform import juju_secret_access.secret-access-name coh2uo2ji6m0ue9a7tj0
```
10 changes: 10 additions & 0 deletions examples/resources/juju_secret/import.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Secrets can be imported by using the URI as in the juju show-secrets output.
# Example:
# $juju show-secret secret-name
# coh2uo2ji6m0ue9a7tj0:
# revision: 1
# owner: <model>
# name: secret-name
# created: 2024-04-19T08:46:25Z
# updated: 2024-04-19T08:46:25Z
$ terraform import juju_secret.secret-name coh2uo2ji6m0ue9a7tj0
9 changes: 9 additions & 0 deletions examples/resources/juju_secret/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
resource "juju_secret" "this" {
model = juju_model.development.name
name = "this_secret_name"
value = {
key1 = "value1"
key2 = "value2"
}
info = "This is the secret"
}
10 changes: 10 additions & 0 deletions examples/resources/juju_secret_access/import.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Secret access can be imported by using the URI as in the juju show-secrets output.
# Example:
# $juju show-secret secret-name
# coh2uo2ji6m0ue9a7tj0:
# revision: 1
# owner: <model>
# name: secret-name
# created: 2024-04-19T08:46:25Z
# updated: 2024-04-19T08:46:25Z
$ terraform import juju_secret_access.secret-access-name coh2uo2ji6m0ue9a7tj0
7 changes: 7 additions & 0 deletions examples/resources/juju_secret_access/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
resource "juju_secret_access" "this" {
model = juju_model.development.name
applications = [
juju_application.app.name, juju_application.app2.name
]
secret_id = juju_secret.that.secret_id
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ require (
github.com/juju/cmd/v3 v3.0.14
github.com/juju/collections v1.0.4
github.com/juju/errors v1.0.0
github.com/juju/names/v4 v4.0.0
github.com/juju/names/v5 v5.0.0
github.com/juju/retry v1.0.0
github.com/juju/utils/v3 v3.1.1
Expand Down Expand Up @@ -128,7 +129,6 @@ require (
github.com/juju/lumberjack/v2 v2.0.2 // indirect
github.com/juju/mgo/v3 v3.0.4 // indirect
github.com/juju/mutex/v2 v2.0.0 // indirect
github.com/juju/names/v4 v4.0.0-20220207005702-9c6532a52823 // indirect
github.com/juju/os/v2 v2.2.3 // indirect
github.com/juju/packaging/v2 v2.0.1 // indirect
github.com/juju/persistent-cookiejar v1.0.0 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -368,8 +368,8 @@ github.com/juju/mgo/v3 v3.0.4 h1:ek6YDy71tqikpoFSpvLkpCZ7zvYNYH+xSk/MebMkCEE=
github.com/juju/mgo/v3 v3.0.4/go.mod h1:fAvhDCRbUlEbRIae6UQT8RvPUoLwKnJsBgO6OzHKNxw=
github.com/juju/mutex/v2 v2.0.0 h1:rVmJdOaXGWF8rjcFHBNd4x57/1tks5CgXHx55O55SB0=
github.com/juju/mutex/v2 v2.0.0/go.mod h1:jwCfBs/smYDaeZLqeaCi8CB8M+tOes4yf827HoOEoqk=
github.com/juju/names/v4 v4.0.0-20220207005702-9c6532a52823 h1:Sv0+v4107/GHA0S25ay/rgGVmLyc+5Fjp0NnTksW/IQ=
github.com/juju/names/v4 v4.0.0-20220207005702-9c6532a52823/go.mod h1:xpkrQpHbz1DGY+0Geo32ZnyognGA/2vSB++rpu/Z+Lc=
github.com/juju/names/v4 v4.0.0 h1:XeQZbwT70i98TynM+2RJr9At6EGb9X/P6l8qF56hPns=
github.com/juju/names/v4 v4.0.0/go.mod h1:xpkrQpHbz1DGY+0Geo32ZnyognGA/2vSB++rpu/Z+Lc=
github.com/juju/names/v5 v5.0.0 h1:3IkRTUaniNXsgjy4lNqbJx7dVdsONlzuH6YMYT7uXss=
github.com/juju/names/v5 v5.0.0/go.mod h1:PkvHbErUTniKvLu1ejJ5m/AbXOW55MFn1jsGVEbVXk8=
github.com/juju/naturalsort v1.0.0 h1:kGmUUy3h8mJ5/SJYaqKOBR3f3owEd5R52Lh+Tjg/dNM=
Expand Down
2 changes: 1 addition & 1 deletion internal/juju/applications_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
"github.com/juju/juju/core/resources"
"github.com/juju/juju/environs/config"
"github.com/juju/juju/rpc/params"
"github.com/juju/names/v5"
"github.com/juju/names/v4"
"github.com/juju/utils/v3"
"github.com/juju/version/v2"
"github.com/stretchr/testify/suite"
Expand Down
1 change: 1 addition & 0 deletions internal/juju/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const (
PrefixCharm = "charm-"
PrefixUser = "user-"
PrefixMachine = "machine-"
PrefixApplication = "application-"
UnspecifiedRevision = -1
connectionTimeout = 30 * time.Second
)
Expand Down
31 changes: 23 additions & 8 deletions internal/juju/secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,11 @@ type ReadSecretInput struct {
}

type ReadSecretOutput struct {
SecretId string
Name string
Value map[string]string
Info string
SecretId string
Name string
Value map[string]string
Applications []string
Info string
}

type UpdateSecretInput struct {
Expand Down Expand Up @@ -176,11 +177,15 @@ func (c *secretsClient) ReadSecret(input *ReadSecretInput) (ReadSecretOutput, er
return ReadSecretOutput{}, err
}

// Get applications from Access info
applications := getApplicationsFromAccessInfo(results[0].Access)

return ReadSecretOutput{
SecretId: results[0].Metadata.URI.String(),
Name: results[0].Metadata.Label,
Value: decodedValue,
Info: results[0].Metadata.Description,
SecretId: results[0].Metadata.URI.String(),
Name: results[0].Metadata.Label,
Value: decodedValue,
Applications: applications,
Info: results[0].Metadata.Description,
}, nil
}

Expand Down Expand Up @@ -301,3 +306,13 @@ func (c *secretsClient) UpdateSecretAccess(input *GrantRevokeSecretAccessInput,

return nil
}

// getApplicationsFromAccessInfo returns a list of applications from the access info.
func getApplicationsFromAccessInfo(accessInfo []coresecrets.AccessInfo) []string {
applications := make([]string, 0, len(accessInfo))
for _, info := range accessInfo {
// Trim the prefix "application-" from the application name (info.Target)
applications = append(applications, strings.TrimPrefix(info.Target, PrefixApplication))
}
return applications
}
19 changes: 10 additions & 9 deletions internal/provider/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,16 @@ const (
LogDataSourceModel = "datasource-model"
LogDataSourceOffer = "datasource-offer"

LogResourceApplication = "resource-application"
LogResourceAccessModel = "resource-assess-model"
LogResourceCredential = "resource-credential"
LogResourceMachine = "resource-machine"
LogResourceModel = "resource-model"
LogResourceOffer = "resource-offer"
LogResourceSSHKey = "resource-sshkey"
LogResourceUser = "resource-user"
LogResourceSecret = "resource-secret"
LogResourceApplication = "resource-application"
LogResourceAccessModel = "resource-assess-model"
LogResourceCredential = "resource-credential"
LogResourceMachine = "resource-machine"
LogResourceModel = "resource-model"
LogResourceOffer = "resource-offer"
LogResourceSSHKey = "resource-sshkey"
LogResourceUser = "resource-user"
LogResourceSecret = "resource-secret"
LogResourceSecretAccess = "resource-secret-access"
)

const LogResourceIntegration = "resource-integration"
Expand Down
1 change: 1 addition & 0 deletions internal/provider/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const TestCloudEnvKey string = "TEST_CLOUD"
const TestMachineIPEnvKey string = "TEST_ADD_MACHINE_IP"
const TestSSHPublicKeyFileEnvKey string = "TEST_SSH_PUB_KEY_PATH"
const TestSSHPrivateKeyFileEnvKey string = "TEST_SSH_PRIV_KEY_PATH"
const TestJujuAgentVersion = "JUJU_AGENT_VERSION"

// CloudTesting is a value indicating the current cloud
// available for testing
Expand Down
1 change: 1 addition & 0 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@ func (p *jujuProvider) Resources(_ context.Context) []func() resource.Resource {
func() resource.Resource { return NewSSHKeyResource() },
func() resource.Resource { return NewUserResource() },
func() resource.Resource { return NewSecretResource() },
func() resource.Resource { return NewSecretAccessResource() },
}
}

Expand Down
2 changes: 1 addition & 1 deletion internal/provider/resource_model.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/juju/juju/core/constraints"
"github.com/juju/names/v5"
"github.com/juju/names/v4"
"github.com/juju/utils/v3"

"github.com/juju/terraform-provider-juju/internal/juju"
Expand Down
3 changes: 3 additions & 0 deletions internal/provider/resource_secret.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ func (s *secretResource) Schema(_ context.Context, req resource.SchemaRequest, r
"secret_id": schema.StringAttribute{
Description: "The ID of the secret.",
Computed: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.UseStateForUnknown(),
},
},
"info": schema.StringAttribute{
Description: "The description of the secret.",
Expand Down
Loading

0 comments on commit 2769399

Please sign in to comment.