1
0
Fork 0
mirror of https://github.com/external-secrets/external-secrets.git synced 2024-12-14 11:57:59 +00:00

Merge pull request #700 from EladGabay/elad/oci-secret-by-name

oracle vault: Use instance principal if auth is empty
This commit is contained in:
paul-the-alien[bot] 2022-02-10 10:34:40 +00:00 committed by GitHub
commit 027f28ec97
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 168 additions and 130 deletions

View file

@ -19,31 +19,33 @@ import (
// Configures an store to sync secrets using a Oracle Vault
// backend.
type OracleProvider struct {
// Auth configures how secret-manager authenticates with the Oracle Vault.
Auth OracleAuth `json:"auth"`
// User is an access OCID specific to the account.
User string `json:"user,omitempty"`
// Tenancy is the tenancy OCID where secret is located.
Tenancy string `json:"tenancy,omitempty"`
// Region is the region where secret is located.
Region string `json:"region,omitempty"`
// Region is the region where vault is located.
Region string `json:"region"`
// Vault is the vault's OCID of the specific vault where secret is located.
Vault string `json:"vault,omitempty"`
Vault string `json:"vault"`
// Auth configures how secret-manager authenticates with the Oracle Vault.
// If empty, use the instance principal, otherwise the user credentials specified in Auth.
// +optional
Auth *OracleAuth `json:"auth,omitempty"`
}
type OracleAuth struct {
// Tenancy is the tenancy OCID where user is located.
Tenancy string `json:"tenancy"`
// User is an access OCID specific to the account.
User string `json:"user"`
// SecretRef to pass through sensitive information.
SecretRef OracleSecretRef `json:"secretRef"`
}
type OracleSecretRef struct {
// PrivateKey is the user's API Signing Key in PEM format, used for authentication.
PrivateKey esmeta.SecretKeySelector `json:"privatekey,omitempty"`
PrivateKey esmeta.SecretKeySelector `json:"privatekey"`
// Fingerprint is the fingerprint of the API private key.
Fingerprint esmeta.SecretKeySelector `json:"fingerprint,omitempty"`
Fingerprint esmeta.SecretKeySelector `json:"fingerprint"`
}

View file

@ -836,7 +836,11 @@ func (in *OracleAuth) DeepCopy() *OracleAuth {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *OracleProvider) DeepCopyInto(out *OracleProvider) {
*out = *in
in.Auth.DeepCopyInto(&out.Auth)
if in.Auth != nil {
in, out := &in.Auth, &out.Auth
*out = new(OracleAuth)
(*in).DeepCopyInto(*out)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OracleProvider.

View file

@ -558,7 +558,8 @@ spec:
properties:
auth:
description: Auth configures how secret-manager authenticates
with the Oracle Vault.
with the Oracle Vault. If empty, use the instance principal,
otherwise the user credentials specified in Auth.
properties:
secretRef:
description: SecretRef to pass through sensitive information.
@ -605,25 +606,32 @@ spec:
the referent.
type: string
type: object
required:
- fingerprint
- privatekey
type: object
tenancy:
description: Tenancy is the tenancy OCID where user is
located.
type: string
user:
description: User is an access OCID specific to the account.
type: string
required:
- secretRef
- tenancy
- user
type: object
region:
description: Region is the region where secret is located.
type: string
tenancy:
description: Tenancy is the tenancy OCID where secret is located.
type: string
user:
description: User is an access OCID specific to the account.
description: Region is the region where vault is located.
type: string
vault:
description: Vault is the vault's OCID of the specific vault
where secret is located.
type: string
required:
- auth
- region
- vault
type: object
vault:
description: Vault configures this store to sync secrets using

View file

@ -561,7 +561,8 @@ spec:
properties:
auth:
description: Auth configures how secret-manager authenticates
with the Oracle Vault.
with the Oracle Vault. If empty, use the instance principal,
otherwise the user credentials specified in Auth.
properties:
secretRef:
description: SecretRef to pass through sensitive information.
@ -608,25 +609,32 @@ spec:
the referent.
type: string
type: object
required:
- fingerprint
- privatekey
type: object
tenancy:
description: Tenancy is the tenancy OCID where user is
located.
type: string
user:
description: User is an access OCID specific to the account.
type: string
required:
- secretRef
- tenancy
- user
type: object
region:
description: Region is the region where secret is located.
type: string
tenancy:
description: Tenancy is the tenancy OCID where secret is located.
type: string
user:
description: User is an access OCID specific to the account.
description: Region is the region where vault is located.
type: string
vault:
description: Vault is the vault's OCID of the specific vault
where secret is located.
type: string
required:
- auth
- region
- vault
type: object
vault:
description: Vault configures this store to sync secrets using

View file

@ -4,7 +4,10 @@ External Secrets Operator integrates with [OCI API](https://github.com/oracle/oc
### Authentication
The API requires a userOCID, tenancyOCID, fingerprint, key file and a region. The fingerprint and key file should be supplied in the secret with the rest being provided in the secret store.
If `auth` is not specified, the operator uses the instance principal.
For using a specific user credentials, userOCID, tenancyOCID, fingerprint and private key are required.
The fingerprint and key file should be supplied in the secret with the rest being provided in the secret store.
See url for what region you you are accessing.
![userOCID-details](./pictures/screenshot_region.png)

View file

@ -1,19 +1,31 @@
apiVersion: external-secrets.io/v1alpha1
kind: SecretStore
metadata:
name: example
name: example-instance-principal
spec:
provider:
oracle: #Needs to match value in secretstore_types.go
oracle:
vault: # The vault OCID
user:
tenancy:
region:
region: # The vault region
---
apiVersion: external-secrets.io/v1alpha1
kind: SecretStore
metadata:
name: example-auth
spec:
provider:
oracle:
vault: # The vault OCID
region: # The vault region
auth:
user: # A user OCID
tenancy: # A user's tenancy
secretRef:
privatekey:
name: oracle-secret
key: privateKey #Needs to match stringData val in secret_oracle.yml
key: privateKey
fingerprint:
name: oracle-secret
key: fingerprint

View file

@ -21,8 +21,8 @@ import (
// nolint
. "github.com/onsi/gomega"
"github.com/oracle/oci-go-sdk/v45/common"
vault "github.com/oracle/oci-go-sdk/v45/vault"
"github.com/oracle/oci-go-sdk/v56/common"
vault "github.com/oracle/oci-go-sdk/v56/vault"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
utilpointer "k8s.io/utils/pointer"
@ -113,7 +113,11 @@ func (p *oracleProvider) BeforeEach() {
Spec: esv1alpha1.SecretStoreSpec{
Provider: &esv1alpha1.SecretStoreProvider{
Oracle: &esv1alpha1.OracleProvider{
Auth: esv1alpha1.OracleAuth{
Region: p.region,
Vault: "vaultOCID",
Auth: &esv1alpha1.OracleAuth{
Tenancy: p.tenancy,
User: p.user,
SecretRef: esv1alpha1.OracleSecretRef{
Fingerprint: esmeta.SecretKeySelector{
Name: "vms-secret",

3
go.mod
View file

@ -59,7 +59,7 @@ require (
github.com/lestrrat-go/jwx v1.2.1
github.com/onsi/ginkgo/v2 v2.1.1
github.com/onsi/gomega v1.18.1
github.com/oracle/oci-go-sdk/v45 v45.2.0
github.com/oracle/oci-go-sdk/v56 v56.1.0
github.com/prometheus/client_golang v1.12.1
github.com/prometheus/client_model v0.2.0
github.com/stretchr/testify v1.7.0
@ -181,6 +181,7 @@ require (
github.com/russross/blackfriday/v2 v2.0.1 // indirect
github.com/ryanuber/go-glob v1.0.0 // indirect
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
github.com/sony/gobreaker v0.4.2-0.20210216022020-dd874f9dd33b // indirect
github.com/spf13/cobra v1.2.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/objx v0.2.0 // indirect

6
go.sum
View file

@ -693,8 +693,8 @@ github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAl
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/oracle/oci-go-sdk/v45 v45.2.0 h1:vCPoQlE+DOrM2heJn66rvPU6fbsc/0Cxtzs2jnFut6U=
github.com/oracle/oci-go-sdk/v45 v45.2.0/go.mod h1:ZM6LGiRO5TPQJxTlrXbcHMbClE775wnGD5U/EerCsRw=
github.com/oracle/oci-go-sdk/v56 v56.1.0 h1:HOr9P+MkwgrilEGTJCU7a6GMFrUG/RZAzvh/2JeRXvI=
github.com/oracle/oci-go-sdk/v56 v56.1.0/go.mod h1:kDJAL3HEAF+4oQR8GfaOkY6rz2kU3/kZ6vYJnJXSCkA=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
@ -772,6 +772,8 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0=
github.com/sony/gobreaker v0.4.2-0.20210216022020-dd874f9dd33b h1:br+bPNZsJWKicw/5rALEo67QHs5weyD5tf8WST+4sJ0=
github.com/sony/gobreaker v0.4.2-0.20210216022020-dd874f9dd33b/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=

View file

@ -16,7 +16,7 @@ package fake
import (
"context"
secrets "github.com/oracle/oci-go-sdk/v45/secrets"
secrets "github.com/oracle/oci-go-sdk/v56/secrets"
)
type OracleMockClient struct {

View file

@ -17,14 +17,16 @@ import (
"encoding/json"
"fmt"
"github.com/oracle/oci-go-sdk/v45/common"
"github.com/oracle/oci-go-sdk/v45/secrets"
"github.com/oracle/oci-go-sdk/v56/common"
"github.com/oracle/oci-go-sdk/v56/common/auth"
"github.com/oracle/oci-go-sdk/v56/secrets"
"github.com/tidwall/gjson"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
kclient "sigs.k8s.io/controller-runtime/pkg/client"
esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
"github.com/external-secrets/external-secrets/pkg/provider"
"github.com/external-secrets/external-secrets/pkg/provider/aws/util"
"github.com/external-secrets/external-secrets/pkg/provider/schema"
@ -52,18 +54,6 @@ const (
errUnexpectedContent = "unexpected secret bundle content"
)
type client struct {
kube kclient.Client
store *esv1alpha1.OracleProvider
namespace string
storeKind string
tenancy string
user string
region string
fingerprint string
privateKey string
}
type VaultManagementService struct {
Client VMInterface
vault string
@ -73,58 +63,6 @@ type VMInterface interface {
GetSecretBundleByName(ctx context.Context, request secrets.GetSecretBundleByNameRequest) (secrets.GetSecretBundleByNameResponse, error)
}
func (c *client) setAuth(ctx context.Context) error {
credentialsSecret := &corev1.Secret{}
credentialsSecretName := c.store.Auth.SecretRef.PrivateKey.Name
if credentialsSecretName == "" {
return fmt.Errorf(errORACLECredSecretName)
}
objectKey := types.NamespacedName{
Name: credentialsSecretName,
Namespace: c.namespace,
}
// only ClusterStore is allowed to set namespace (and then it's required)
if c.storeKind == esv1alpha1.ClusterSecretStoreKind {
if c.store.Auth.SecretRef.PrivateKey.Namespace == nil {
return fmt.Errorf(errInvalidClusterStoreMissingSKNamespace)
}
objectKey.Namespace = *c.store.Auth.SecretRef.PrivateKey.Namespace
}
err := c.kube.Get(ctx, objectKey, credentialsSecret)
if err != nil {
return fmt.Errorf(errFetchSAKSecret, err)
}
c.privateKey = string(credentialsSecret.Data[c.store.Auth.SecretRef.PrivateKey.Key])
if c.privateKey == "" {
return fmt.Errorf(errMissingPK)
}
c.fingerprint = string(credentialsSecret.Data[c.store.Auth.SecretRef.Fingerprint.Key])
if c.fingerprint == "" {
return fmt.Errorf(errMissingFingerprint)
}
c.user = c.store.User
if c.user == "" {
return fmt.Errorf(errMissingUser)
}
c.tenancy = c.store.Tenancy
if c.tenancy == "" {
return fmt.Errorf(errMissingTenancy)
}
c.region = c.store.Region
if c.region == "" {
return fmt.Errorf(errMissingRegion)
}
return nil
}
func (vms *VaultManagementService) GetSecret(ctx context.Context, ref esv1alpha1.ExternalSecretDataRemoteRef) ([]byte, error) {
if utils.IsNil(vms.Client) {
return nil, fmt.Errorf(errUninitalizedOracleProvider)
@ -188,35 +126,91 @@ func (vms *VaultManagementService) NewClient(ctx context.Context, store esv1alph
return nil, fmt.Errorf(errMissingVault)
}
oracleStore := &client{
kube: kube,
store: oracleSpec,
namespace: namespace,
storeKind: store.GetObjectKind().GroupVersionKind().Kind,
}
if err := oracleStore.setAuth(ctx); err != nil {
return nil, err
if oracleSpec.Region == "" {
return nil, fmt.Errorf(errMissingRegion)
}
oracleTenancy := oracleStore.tenancy
oracleUser := oracleStore.user
oracleRegion := oracleStore.region
oracleFingerprint := oracleStore.fingerprint
oraclePrivateKey := oracleStore.privateKey
configurationProvider := common.NewRawConfigurationProvider(oracleTenancy, oracleUser, oracleRegion, oracleFingerprint, oraclePrivateKey, nil)
var (
err error
configurationProvider common.ConfigurationProvider
)
if oracleSpec.Auth == nil {
configurationProvider, err = auth.InstancePrincipalConfigurationProvider()
} else {
configurationProvider, err = getUserAuthConfigurationProvider(ctx, kube, oracleSpec, namespace, store.GetObjectKind().GroupVersionKind().Kind, oracleSpec.Region)
}
if err != nil {
return nil, fmt.Errorf(errOracleClient, err)
}
secretManagementService, err := secrets.NewSecretsClientWithConfigurationProvider(configurationProvider)
if err != nil {
return nil, fmt.Errorf(errOracleClient, err)
}
secretManagementService.SetRegion(oracleSpec.Region)
return &VaultManagementService{
Client: secretManagementService,
vault: oracleSpec.Vault,
}, nil
}
func getSecretData(ctx context.Context, kube kclient.Client, namespace, storeKind string, secretRef esmeta.SecretKeySelector) (string, error) {
if secretRef.Name == "" {
return "", fmt.Errorf(errORACLECredSecretName)
}
objectKey := types.NamespacedName{
Name: secretRef.Name,
Namespace: namespace,
}
// only ClusterStore is allowed to set namespace (and then it's required)
if storeKind == esv1alpha1.ClusterSecretStoreKind {
if secretRef.Namespace == nil {
return "", fmt.Errorf(errInvalidClusterStoreMissingSKNamespace)
}
objectKey.Namespace = *secretRef.Namespace
}
secret := corev1.Secret{}
err := kube.Get(ctx, objectKey, &secret)
if err != nil {
return "", fmt.Errorf(errFetchSAKSecret, err)
}
return string(secret.Data[secretRef.Key]), nil
}
func getUserAuthConfigurationProvider(ctx context.Context, kube kclient.Client, store *esv1alpha1.OracleProvider, namespace, storeKind, region string) (common.ConfigurationProvider, error) {
privateKey, err := getSecretData(ctx, kube, namespace, storeKind, store.Auth.SecretRef.PrivateKey)
if err != nil {
return nil, err
}
if privateKey == "" {
return nil, fmt.Errorf(errMissingPK)
}
fingerprint, err := getSecretData(ctx, kube, namespace, storeKind, store.Auth.SecretRef.Fingerprint)
if err != nil {
return nil, err
}
if fingerprint == "" {
return nil, fmt.Errorf(errMissingFingerprint)
}
if store.Auth.User == "" {
return nil, fmt.Errorf(errMissingUser)
}
if store.Auth.Tenancy == "" {
return nil, fmt.Errorf(errMissingTenancy)
}
return common.NewRawConfigurationProvider(store.Auth.Tenancy, store.Auth.User, region, fingerprint, privateKey, nil), nil
}
func (vms *VaultManagementService) Close(ctx context.Context) error {
return nil
}

View file

@ -19,7 +19,7 @@ import (
"strings"
"testing"
secrets "github.com/oracle/oci-go-sdk/v45/secrets"
secrets "github.com/oracle/oci-go-sdk/v56/secrets"
utilpointer "k8s.io/utils/pointer"
esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"

View file

@ -17,7 +17,7 @@ package utils
import (
"testing"
vault "github.com/oracle/oci-go-sdk/v45/vault"
vault "github.com/oracle/oci-go-sdk/v56/vault"
v1 "k8s.io/api/core/v1"
)