Skip to content

Commit

Permalink
feat!: Add new methods for SecretStoreClient (#307)
Browse files Browse the repository at this point in the history
* feat: Add new methods for SecretStoreClient

Resolves #306. Add GetIdentityByEntityId and CreateTokenByRole methods for SecretStoreClient.

Signed-off-by: Lindsey Cheng <[email protected]>

* fix: Update interface to any

Signed-off-by: Lindsey Cheng <[email protected]>

---------

Signed-off-by: Lindsey Cheng <[email protected]>
  • Loading branch information
lindseysimple authored Feb 10, 2025
1 parent c260483 commit f4e54c9
Show file tree
Hide file tree
Showing 8 changed files with 194 additions and 9 deletions.
4 changes: 3 additions & 1 deletion internal/pkg/openbao/constants.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*******************************************************************************
* Copyright 2019 Dell Inc.
* Copyright 2021 Intel Corp.
* Copyright 2024 IOTech Ltd
* Copyright 2024-2025 IOTech Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
Expand All @@ -26,6 +26,7 @@ const (
UnsealAPI = "/v1/sys/unseal"
CreatePolicyPath = "/v1/sys/policies/acl/%s"
CreateTokenAPI = "/v1/auth/token/create" // nolint: gosec
CreateTokenByRolePath = "/v1/auth/token/create/%s" // nolint: gosec
ListAccessorsAPI = "/v1/auth/token/accessors" // nolint: gosec
RevokeAccessorAPI = "/v1/auth/token/revoke-accessor"
LookupAccessorAPI = "/v1/auth/token/lookup-accessor"
Expand All @@ -35,6 +36,7 @@ const (
RootTokenRetrievalAPI = "/v1/sys/generate-root/update" // nolint: gosec
MountsAPI = "/v1/sys/mounts"
namedEntityAPI = "/v1/identity/entity/name"
idEntityAPI = "/v1/identity/entity/id"
entityAliasAPI = "/v1/identity/entity-alias"
oidcKeyAPI = "/v1/identity/oidc/key"
oidcRoleAPI = "/v1/identity/oidc/role"
Expand Down
24 changes: 23 additions & 1 deletion internal/pkg/openbao/management.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*******************************************************************************
* Copyright 2019 Dell Inc.
* Copyright 2021 Intel Corp.
* Copyright 2024 IOTech Ltd
* Copyright 2024-2025 IOTech Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
Expand Down Expand Up @@ -250,6 +250,28 @@ func (c *Client) LookupIdentity(secretStoreToken string, name string) (string, e
return response.Data.ID, nil
}

func (c *Client) GetIdentityByEntityId(secretStoreToken string, entityId string) (map[string]any, error) {
urlPath := path.Join(idEntityAPI, entityId)
response := ReadEntityByIdResponse{}

_, err := c.doRequest(RequestArgs{
AuthToken: secretStoreToken,
Method: http.MethodGet,
Path: urlPath,
JSONObject: nil,
BodyReader: nil,
OperationDescription: "Read Entity",
ExpectedStatusCode: http.StatusOK,
ResponseObject: &response,
})

if err != nil {
return map[string]any{}, err
}

return response.Data, nil
}

func (c *Client) CheckAuthMethodEnabled(token string, mountPoint string, authType string) (bool, error) {
var response ListSecretEnginesResponse

Expand Down
31 changes: 30 additions & 1 deletion internal/pkg/openbao/management_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*******************************************************************************
* Copyright 2019 Dell Inc.
* Copyright 2021 Intel Corp.
* Copyright 2024 IOTech Ltd
* Copyright 2024-2025 IOTech Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
Expand Down Expand Up @@ -500,6 +500,35 @@ func TestLookupIdentity(t *testing.T) {
require.Equal(t, id, "someguid")
}

func TestGetIdentityByEntityId(t *testing.T) {
mockId := "074fa04b-0f48-6ce3-53f3-d5cfe8147d7d"

// Arrange
mockLogger := logger.MockLogger{}

ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
require.Equal(t, expectedToken, r.Header.Get(AuthTypeHeader))
require.Equal(t, r.Method, http.MethodGet)
require.Equal(t, path.Join(idEntityAPI, mockId), r.URL.EscapedPath())

w.WriteHeader(http.StatusOK)
response := ReadEntityByIdResponse{}
response.Data = map[string]any{"id": mockId}
err := json.NewEncoder(w).Encode(response)
require.NoError(t, err)
}))
defer ts.Close()

client := createClient(t, ts.URL, mockLogger)

// Act
result, err := client.GetIdentityByEntityId(expectedToken, mockId)

// Assert
require.NoError(t, err)
require.Equal(t, result["id"], mockId)
}

func TestEnablePasswordAuth(t *testing.T) {
// Arrange
mockLogger := logger.MockLogger{}
Expand Down
5 changes: 5 additions & 0 deletions internal/pkg/openbao/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,11 @@ type ReadEntityByNameResponse struct {
Data JsonID `json:"data"`
}

// ReadEntityByIdResponse is the response to get entity by id
type ReadEntityByIdResponse struct {
Data map[string]any `json:"data"`
}

// EnableAuthMethodRequest enables a secret store Identity authentication method
type EnableAuthMethodRequest struct {
Type string `json:"type"`
Expand Down
25 changes: 23 additions & 2 deletions internal/pkg/openbao/token.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//
// Copyright (c) 2021 Intel Corporation
// Copyright 2025 IOTech Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
Expand All @@ -15,13 +16,15 @@
package openbao

import (
"fmt"
"net/http"
"net/url"

"github.com/edgexfoundry/go-mod-secrets/v4/pkg/types"
)

func (c *Client) CreateToken(token string, parameters map[string]interface{}) (map[string]interface{}, error) {
response := make(map[string]interface{})
func (c *Client) CreateToken(token string, parameters map[string]any) (map[string]any, error) {
response := make(map[string]any)

_, err := c.doRequest(RequestArgs{
AuthToken: token,
Expand All @@ -37,6 +40,24 @@ func (c *Client) CreateToken(token string, parameters map[string]interface{}) (m
return response, err
}

func (c *Client) CreateTokenByRole(token string, roleName string, parameters map[string]any) (map[string]any, error) {
response := make(map[string]any)

_, err := c.doRequest(RequestArgs{
AuthToken: token,
Method: http.MethodPost,
//Path: CreateTokenAPI,
Path: fmt.Sprintf(CreateTokenByRolePath, url.PathEscape(roleName)),
JSONObject: parameters,
BodyReader: nil,
OperationDescription: "create token",
ExpectedStatusCode: http.StatusOK,
ResponseObject: &response,
})

return response, err
}

func (c *Client) ListTokenAccessors(token string) ([]string, error) {
var response ListTokenAccessorsResponse

Expand Down
44 changes: 44 additions & 0 deletions internal/pkg/openbao/token_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//
// Copyright (c) 2021 Intel Corporation
// Copyright 2025 IOTech Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
Expand All @@ -16,6 +17,7 @@ package openbao

import (
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"testing"
Expand Down Expand Up @@ -65,6 +67,48 @@ func TestCreateToken(t *testing.T) {
assert.Equal(t, "f00341c1-fad5-f6e6-13fd-235617f858a1", response["request_id"].(string))
}

func TestCreateTokenByRole(t *testing.T) {
mockRole := "role1"

// Arrange
mockLogger := logger.MockLogger{}

ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
require.Equal(t, http.MethodPost, r.Method)
require.Equal(t, fmt.Sprintf(CreateTokenByRolePath, mockRole), r.URL.EscapedPath())
require.Equal(t, expectedToken, r.Header.Get(AuthTypeHeader))

body := make(map[string]interface{})
err := json.NewDecoder(r.Body).Decode(&body)
assert.NoError(t, err)

assert.Equal(t, "sample-value", body["sample_parameter"])

w.WriteHeader(http.StatusOK)

response := struct {
RequestID string `json:"request_id"`
}{
RequestID: "f00341c1-fad5-f6e6-13fd-235617f858a1",
}
err = json.NewEncoder(w).Encode(response)
assert.NoError(t, err)

}))
defer ts.Close()

client := createClient(t, ts.URL, mockLogger)

// Act
parameters := make(map[string]interface{})
parameters["sample_parameter"] = "sample-value"
response, err := client.CreateTokenByRole(expectedToken, mockRole, parameters)

// Assert
require.NoError(t, err)
assert.Equal(t, "f00341c1-fad5-f6e6-13fd-235617f858a1", response["request_id"].(string))
}

func TestListTokenAccessors(t *testing.T) {
// Arrange
mockLogger := logger.MockLogger{}
Expand Down
8 changes: 5 additions & 3 deletions secrets/interfaces.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*******************************************************************************
* Copyright 2019 Dell Inc.
* Copyright 2021 Intel Corp.
* Copyright 2024 IOTech Ltd
* Copyright 2024-2025 IOTech Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
Expand Down Expand Up @@ -59,7 +59,8 @@ type SecretStoreClient interface {
CheckSecretEngineInstalled(token string, mountPoint string, engine string) (bool, error)
EnableKVSecretEngine(token string, mountPoint string, kvVersion string) error
RegenRootToken(keys []string) (string, error)
CreateToken(token string, parameters map[string]interface{}) (map[string]interface{}, error)
CreateToken(token string, parameters map[string]any) (map[string]any, error)
CreateTokenByRole(token string, role string, parameters map[string]any) (map[string]any, error)
ListTokenAccessors(token string) ([]string, error)
RevokeTokenAccessor(token string, accessor string) error
LookupTokenAccessor(token string, accessor string) (types.TokenMetadata, error)
Expand All @@ -68,13 +69,14 @@ type SecretStoreClient interface {
CreateOrUpdateIdentity(token string, name string, metadata map[string]string, policies []string) (string, error)
DeleteIdentity(token string, name string) error
LookupIdentity(token string, name string) (string, error)
GetIdentityByEntityId(token string, entityId string) (map[string]any, error)
CheckAuthMethodEnabled(token string, mountPoint string, authType string) (bool, error)
EnablePasswordAuth(token string, mountPoint string) error
LookupAuthHandle(token string, mountPoint string) (string, error)
CreateOrUpdateUser(token string, mountPoint string, username string, password string, tokenTTL string, tokenPolicies []string) error
DeleteUser(token string, mountPoint string, username string) error
BindUserToIdentity(token string, identityId string, authHandle string, username string) error
InternalServiceLogin(token string, authEngine string, username string, password string) (map[string]interface{}, error)
InternalServiceLogin(token string, authEngine string, username string, password string) (map[string]any, error)
CheckIdentityKeyExists(token string, keyName string) (bool, error)
CreateNamedIdentityKey(token string, keyName string, algorithm string) error
CreateOrUpdateIdentityRole(token string, roleName string, keyName string, template string, audience string, jwtTTL string) error
Expand Down
62 changes: 61 additions & 1 deletion secrets/mocks/SecretStoreClient.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit f4e54c9

Please sign in to comment.