mirror of
https://github.com/external-secrets/external-secrets.git
synced 2024-12-14 11:57:59 +00:00
Merge pull request #596 from EladGabay/elad/oci-secret-by-name
OCI Vault: Get secret by name from a specific Vault
This commit is contained in:
commit
16948ed572
9 changed files with 68 additions and 52 deletions
|
@ -25,11 +25,14 @@ type OracleProvider struct {
|
|||
// User is an access OCID specific to the account.
|
||||
User string `json:"user,omitempty"`
|
||||
|
||||
// projectID is an access token specific to the secret.
|
||||
// Tenancy is the tenancy OCID where secret is located.
|
||||
Tenancy string `json:"tenancy,omitempty"`
|
||||
|
||||
// projectID is an access token specific to the secret.
|
||||
// Region is the region where secret is located.
|
||||
Region string `json:"region,omitempty"`
|
||||
|
||||
// Vault is the vault's OCID of the specific vault where secret is located.
|
||||
Vault string `json:"vault,omitempty"`
|
||||
}
|
||||
|
||||
type OracleAuth struct {
|
||||
|
@ -38,9 +41,9 @@ type OracleAuth struct {
|
|||
}
|
||||
|
||||
type OracleSecretRef struct {
|
||||
// The Access Token is used for authentication
|
||||
// PrivateKey is the user's API Signing Key in PEM format, used for authentication.
|
||||
PrivateKey esmeta.SecretKeySelector `json:"privatekey,omitempty"`
|
||||
|
||||
// projectID is an access token specific to the secret.
|
||||
// Fingerprint is the fingerprint of the API private key.
|
||||
Fingerprint esmeta.SecretKeySelector `json:"fingerprint,omitempty"`
|
||||
}
|
||||
|
|
|
@ -541,8 +541,8 @@ spec:
|
|||
description: SecretRef to pass through sensitive information.
|
||||
properties:
|
||||
fingerprint:
|
||||
description: projectID is an access token specific
|
||||
to the secret.
|
||||
description: Fingerprint is the fingerprint of the
|
||||
API private key.
|
||||
properties:
|
||||
key:
|
||||
description: The key of the entry in the Secret
|
||||
|
@ -562,7 +562,8 @@ spec:
|
|||
type: string
|
||||
type: object
|
||||
privatekey:
|
||||
description: The Access Token is used for authentication
|
||||
description: PrivateKey is the user's API Signing
|
||||
Key in PEM format, used for authentication.
|
||||
properties:
|
||||
key:
|
||||
description: The key of the entry in the Secret
|
||||
|
@ -586,16 +587,18 @@ spec:
|
|||
- secretRef
|
||||
type: object
|
||||
region:
|
||||
description: projectID is an access token specific to the
|
||||
secret.
|
||||
description: Region is the region where secret is located.
|
||||
type: string
|
||||
tenancy:
|
||||
description: projectID is an access token specific to the
|
||||
secret.
|
||||
description: Tenancy is the tenancy OCID where secret is located.
|
||||
type: string
|
||||
user:
|
||||
description: User is an access OCID specific to the account.
|
||||
type: string
|
||||
vault:
|
||||
description: Vault is the vault's OCID of the specific vault
|
||||
where secret is located.
|
||||
type: string
|
||||
required:
|
||||
- auth
|
||||
type: object
|
||||
|
|
|
@ -541,8 +541,8 @@ spec:
|
|||
description: SecretRef to pass through sensitive information.
|
||||
properties:
|
||||
fingerprint:
|
||||
description: projectID is an access token specific
|
||||
to the secret.
|
||||
description: Fingerprint is the fingerprint of the
|
||||
API private key.
|
||||
properties:
|
||||
key:
|
||||
description: The key of the entry in the Secret
|
||||
|
@ -562,7 +562,8 @@ spec:
|
|||
type: string
|
||||
type: object
|
||||
privatekey:
|
||||
description: The Access Token is used for authentication
|
||||
description: PrivateKey is the user's API Signing
|
||||
Key in PEM format, used for authentication.
|
||||
properties:
|
||||
key:
|
||||
description: The key of the entry in the Secret
|
||||
|
@ -586,16 +587,18 @@ spec:
|
|||
- secretRef
|
||||
type: object
|
||||
region:
|
||||
description: projectID is an access token specific to the
|
||||
secret.
|
||||
description: Region is the region where secret is located.
|
||||
type: string
|
||||
tenancy:
|
||||
description: projectID is an access token specific to the
|
||||
secret.
|
||||
description: Tenancy is the tenancy OCID where secret is located.
|
||||
type: string
|
||||
user:
|
||||
description: User is an access OCID specific to the account.
|
||||
type: string
|
||||
vault:
|
||||
description: Vault is the vault's OCID of the specific vault
|
||||
where secret is located.
|
||||
type: string
|
||||
required:
|
||||
- auth
|
||||
type: object
|
||||
|
|
|
@ -32,7 +32,7 @@ This will automatically generate a fingerprint.
|
|||
![API-key-details](./pictures/screenshot_API_key.png)
|
||||
|
||||
### Update secret store
|
||||
Be sure the `oracle` provider is listed in the `Kind=SecretStore`
|
||||
Be sure the `oracle` provider is listed in the `Kind=SecretStore`.
|
||||
|
||||
```yaml
|
||||
{% include 'oracle-secret-store.yaml' %}
|
||||
|
@ -51,4 +51,4 @@ To create a kubernetes secret from the Oracle Cloud Interface secret a`Kind=Exte
|
|||
The operator will fetch the project variable and inject it as a `Kind=Secret`.
|
||||
```
|
||||
kubectl get secret oracle-secret-to-create -o jsonpath='{.data.dev-secret-test}' | base64 -d
|
||||
```
|
||||
```
|
||||
|
|
|
@ -10,7 +10,5 @@ spec:
|
|||
target:
|
||||
name: secret-to-be-created # Name for the secret on the cluster
|
||||
creationPolicy: Owner
|
||||
data:
|
||||
- secretKey:
|
||||
remoteRef:
|
||||
key:
|
||||
dataFrom:
|
||||
- key: the-secret-name
|
||||
|
|
|
@ -5,9 +5,10 @@ metadata:
|
|||
spec:
|
||||
provider:
|
||||
oracle: #Needs to match value in secretstore_types.go
|
||||
user:
|
||||
tenancy:
|
||||
region:
|
||||
vault: # The vault OCID
|
||||
user:
|
||||
tenancy:
|
||||
region:
|
||||
auth:
|
||||
secretRef:
|
||||
privatekey:
|
||||
|
@ -15,4 +16,4 @@ spec:
|
|||
key: privateKey #Needs to match stringData val in secret_oracle.yml
|
||||
fingerprint:
|
||||
name: oracle-secret
|
||||
key: fingerprint
|
||||
key: fingerprint
|
||||
|
|
|
@ -20,16 +20,16 @@ import (
|
|||
)
|
||||
|
||||
type OracleMockClient struct {
|
||||
getSecret func(ctx context.Context, request secrets.GetSecretBundleRequest) (response secrets.GetSecretBundleResponse, err error)
|
||||
getSecret func(ctx context.Context, request secrets.GetSecretBundleByNameRequest) (response secrets.GetSecretBundleByNameResponse, err error)
|
||||
}
|
||||
|
||||
func (mc *OracleMockClient) GetSecretBundle(ctx context.Context, request secrets.GetSecretBundleRequest) (response secrets.GetSecretBundleResponse, err error) {
|
||||
func (mc *OracleMockClient) GetSecretBundleByName(ctx context.Context, request secrets.GetSecretBundleByNameRequest) (response secrets.GetSecretBundleByNameResponse, err error) {
|
||||
return mc.getSecret(ctx, request)
|
||||
}
|
||||
|
||||
func (mc *OracleMockClient) WithValue(input secrets.GetSecretBundleRequest, output secrets.GetSecretBundleResponse, err error) {
|
||||
func (mc *OracleMockClient) WithValue(input secrets.GetSecretBundleByNameRequest, output secrets.GetSecretBundleByNameResponse, err error) {
|
||||
if mc != nil {
|
||||
mc.getSecret = func(ctx context.Context, paramReq secrets.GetSecretBundleRequest) (secrets.GetSecretBundleResponse, error) {
|
||||
mc.getSecret = func(ctx context.Context, paramReq secrets.GetSecretBundleByNameRequest) (secrets.GetSecretBundleByNameResponse, error) {
|
||||
return output, err
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/oracle/oci-go-sdk/v45/common"
|
||||
secrets "github.com/oracle/oci-go-sdk/v45/secrets"
|
||||
"github.com/oracle/oci-go-sdk/v45/secrets"
|
||||
"github.com/tidwall/gjson"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
|
@ -46,6 +46,7 @@ const (
|
|||
errMissingTenancy = "missing Tenancy ID"
|
||||
errMissingRegion = "missing Region"
|
||||
errMissingFingerprint = "missing Fingerprint"
|
||||
errMissingVault = "missing Vault"
|
||||
errJSONSecretUnmarshal = "unable to unmarshal secret: %w"
|
||||
errMissingKey = "missing Key in secret: %s"
|
||||
errUnexpectedContent = "unexpected secret bundle content"
|
||||
|
@ -65,10 +66,11 @@ type client struct {
|
|||
|
||||
type VaultManagementService struct {
|
||||
Client VMInterface
|
||||
vault string
|
||||
}
|
||||
|
||||
type VMInterface interface {
|
||||
GetSecretBundle(ctx context.Context, request secrets.GetSecretBundleRequest) (response secrets.GetSecretBundleResponse, err error)
|
||||
GetSecretBundleByName(ctx context.Context, request secrets.GetSecretBundleByNameRequest) (secrets.GetSecretBundleByNameResponse, error)
|
||||
}
|
||||
|
||||
func (c *client) setAuth(ctx context.Context) error {
|
||||
|
@ -127,22 +129,22 @@ func (vms *VaultManagementService) GetSecret(ctx context.Context, ref esv1alpha1
|
|||
if utils.IsNil(vms.Client) {
|
||||
return nil, fmt.Errorf(errUninitalizedOracleProvider)
|
||||
}
|
||||
sec, err := vms.Client.GetSecretBundle(ctx, secrets.GetSecretBundleRequest{
|
||||
SecretId: &ref.Key,
|
||||
Stage: secrets.GetSecretBundleStageEnum(ref.Version),
|
||||
})
|
||||
|
||||
sec, err := vms.Client.GetSecretBundleByName(ctx, secrets.GetSecretBundleByNameRequest{
|
||||
VaultId: &vms.vault,
|
||||
SecretName: &ref.Key,
|
||||
Stage: secrets.GetSecretBundleByNameStageEnum(ref.Version),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, util.SanitizeErr(err)
|
||||
}
|
||||
// TODO: should bt.Content be base64 decoded??
|
||||
|
||||
bt, ok := sec.SecretBundleContent.(secrets.Base64SecretBundleContentDetails)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(errUnexpectedContent)
|
||||
}
|
||||
|
||||
payload, err := base64.StdEncoding.DecodeString(*bt.Content)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -182,6 +184,10 @@ func (vms *VaultManagementService) NewClient(ctx context.Context, store esv1alph
|
|||
storeSpec := store.GetSpec()
|
||||
oracleSpec := storeSpec.Provider.Oracle
|
||||
|
||||
if oracleSpec.Vault == "" {
|
||||
return nil, fmt.Errorf(errMissingVault)
|
||||
}
|
||||
|
||||
oracleStore := &client{
|
||||
kube: kube,
|
||||
store: oracleSpec,
|
||||
|
@ -204,8 +210,11 @@ func (vms *VaultManagementService) NewClient(ctx context.Context, store esv1alph
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf(errOracleClient, err)
|
||||
}
|
||||
vms.Client = secretManagementService
|
||||
return vms, nil
|
||||
|
||||
return &VaultManagementService{
|
||||
Client: secretManagementService,
|
||||
vault: oracleSpec.Vault,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (vms *VaultManagementService) Close(ctx context.Context) error {
|
||||
|
|
|
@ -28,8 +28,8 @@ import (
|
|||
|
||||
type vaultTestCase struct {
|
||||
mockClient *fakeoracle.OracleMockClient
|
||||
apiInput *secrets.GetSecretBundleRequest
|
||||
apiOutput *secrets.GetSecretBundleResponse
|
||||
apiInput *secrets.GetSecretBundleByNameRequest
|
||||
apiOutput *secrets.GetSecretBundleByNameResponse
|
||||
ref *esv1alpha1.ExternalSecretDataRemoteRef
|
||||
apiErr error
|
||||
expectError string
|
||||
|
@ -60,15 +60,15 @@ func makeValidRef() *esv1alpha1.ExternalSecretDataRemoteRef {
|
|||
}
|
||||
}
|
||||
|
||||
func makeValidAPIInput() *secrets.GetSecretBundleRequest {
|
||||
return &secrets.GetSecretBundleRequest{
|
||||
SecretId: utilpointer.StringPtr("test-secret"),
|
||||
func makeValidAPIInput() *secrets.GetSecretBundleByNameRequest {
|
||||
return &secrets.GetSecretBundleByNameRequest{
|
||||
SecretName: utilpointer.StringPtr("test-secret"),
|
||||
VaultId: utilpointer.StringPtr("test-vault"),
|
||||
}
|
||||
}
|
||||
|
||||
func makeValidAPIOutput() *secrets.GetSecretBundleResponse {
|
||||
return &secrets.GetSecretBundleResponse{
|
||||
Etag: utilpointer.StringPtr("test-name"),
|
||||
func makeValidAPIOutput() *secrets.GetSecretBundleByNameResponse {
|
||||
return &secrets.GetSecretBundleByNameResponse{
|
||||
SecretBundle: secrets.SecretBundle{},
|
||||
}
|
||||
}
|
||||
|
@ -99,8 +99,7 @@ func TestOracleVaultGetSecret(t *testing.T) {
|
|||
// good case: default version is set
|
||||
// key is passed in, output is sent back
|
||||
setSecretString := func(smtc *vaultTestCase) {
|
||||
smtc.apiOutput = &secrets.GetSecretBundleResponse{
|
||||
Etag: utilpointer.StringPtr("test-name"),
|
||||
smtc.apiOutput = &secrets.GetSecretBundleByNameResponse{
|
||||
SecretBundle: secrets.SecretBundle{
|
||||
SecretId: utilpointer.StringPtr("test-id"),
|
||||
VersionNumber: utilpointer.Int64(1),
|
||||
|
|
Loading…
Reference in a new issue