-
Notifications
You must be signed in to change notification settings - Fork 218
Feat: Added Oracle Cloud Infrastructure(OCI) Vault service as a backend with vaultid #670
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
Open
ddevadat
wants to merge
15
commits into
argoproj-labs:main
Choose a base branch
from
ddevadat:oci-one-vault
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 13 commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
f19e691
feat: Added new backend for Oracle Cloud Infrastructure Vault service
ddevadat d5b5b8f
fix: Fetch latest version when no version specified
ddevadat 5e4c3f8
feat: Added support for oci api key based authentication
ddevadat d3fdf51
docs: Updated example policy for OCI instance principal authentication
ddevadat 5105a64
feat: Added vault and compartment id for OCI based backedn
ddevadat 12cbc45
docs: Updated minor typo errors in the documentation section
ddevadat ee75568
docs: Updated oci vault id ref pattern
ddevadat d453c56
docs: Updated typo error for OCI path pattern
ddevadat 12b7c5e
Merge remote-tracking branch 'upstream/main' into oci-one-vault
ddevadat c2ae912
fix: Updated go.mod files
ddevadat a34bc10
Merge pull request #3 from ddevadat/oci-one-vault
ddevadat d71a432
fix: prevent multiple secret lookup for individual secrets
ddevadat 7ca1b9c
Merge pull request #5 from ddevadat/oci-vault-quick
ddevadat 80d1b25
docs: corrected typo error in comments
ddevadat 7e93dc0
Merge pull request #6 from ddevadat/pr-670-fix-1
ddevadat File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,180 @@ | ||
| package backends | ||
|
|
||
| import ( | ||
| "context" | ||
| "fmt" | ||
| "regexp" | ||
| "strconv" | ||
| "strings" | ||
|
|
||
| "github.com/oracle/oci-go-sdk/v65/common" | ||
| "github.com/oracle/oci-go-sdk/v65/example/helpers" | ||
| ocism "github.com/oracle/oci-go-sdk/v65/secrets" | ||
| ocivault "github.com/oracle/oci-go-sdk/v65/vault" | ||
| ) | ||
|
|
||
| var OCIPath, _ = regexp.Compile(`^ocivault(?:/(.+))?$`) | ||
| var OCISecretVersion, _ = regexp.Compile(`^\d+$`) | ||
|
|
||
| type OCISecretIface interface { | ||
| GetSecretBundleByName(ctx context.Context, request ocism.GetSecretBundleByNameRequest) (response ocism.GetSecretBundleByNameResponse, err error) | ||
| } | ||
|
|
||
| type OCIVaultIface interface { | ||
| ListSecrets(ctx context.Context, request ocivault.ListSecretsRequest) (response ocivault.ListSecretsResponse, err error) | ||
| ListSecretVersions(ctx context.Context, request ocivault.ListSecretVersionsRequest) (response ocivault.ListSecretVersionsResponse, err error) | ||
| } | ||
|
|
||
| // OCIVault is a struct for working with a OCI Vault backend | ||
| type OCIVault struct { | ||
| secretClient OCISecretIface | ||
| vaultClient OCIVaultIface | ||
| vaultId string | ||
| compartmentId string | ||
| } | ||
|
|
||
| // NewOCIVaultBackend initializes a new OCI Vault backend | ||
| func NewOCIVaultBackend(secret_client OCISecretIface,vault_client OCIVaultIface, vault_id string, compartment_id string ) *OCIVault { | ||
| return &OCIVault{ | ||
| secretClient: secret_client, | ||
| vaultClient: vault_client, | ||
| vaultId: vault_id, | ||
| compartmentId: compartment_id, | ||
| } | ||
| } | ||
|
|
||
| // Login does nothing as a "login" is handled on the instantiation of the aws sdk | ||
| func (oci *OCIVault) Login() error { | ||
| return nil | ||
| } | ||
|
|
||
|
|
||
| // Iterate Secret Version | ||
| func (oci *OCIVault) CheckSecretVersion(secret_version_req ocivault.ListSecretVersionsRequest, version int64 ) (bool,error) { | ||
|
|
||
| version_found := false | ||
|
|
||
| listSecretVersionFunc := func(request ocivault.ListSecretVersionsRequest) (ocivault.ListSecretVersionsResponse, error) { | ||
| return oci.vaultClient.ListSecretVersions(context.Background(), request) | ||
| } | ||
|
|
||
| for r, err := listSecretVersionFunc(secret_version_req); ; r, err = listSecretVersionFunc(secret_version_req) { | ||
| if err != nil{ | ||
| return version_found,err | ||
| } | ||
|
|
||
| for _, secret_ver_summary := range r.Items { | ||
| if secret_ver_summary.VersionNumber != nil && *secret_ver_summary.VersionNumber == version { | ||
| version_found=true | ||
| break | ||
| } | ||
| } | ||
|
|
||
| if r.OpcNextPage != nil && !version_found { | ||
| // if there are more items in next page, fetch items from next page | ||
| secret_version_req.Page = r.OpcNextPage | ||
| } else { | ||
| // no more result, break the loop | ||
| break | ||
| } | ||
| } | ||
|
|
||
| return version_found,nil | ||
| } | ||
|
|
||
| // GetSecrets gets secrets from OCI Vault and returns the formatted data | ||
| // For OCI Vault, the path is of format `ocivault/secretname` | ||
|
|
||
| func (oci *OCIVault) GetSecrets(kvpath string, version string, annotations map[string]string) (map[string]interface{}, error) { | ||
|
|
||
| var secretName *string = nil | ||
| matches := OCIPath.FindStringSubmatch(kvpath) | ||
| if len(matches) == 0 { | ||
| return nil, fmt.Errorf("path is not in the correct format (ocivault/) for OCI vault: %s", kvpath) | ||
| } | ||
|
|
||
| if len(matches) > 1 && matches[1] != "" { | ||
| secretName = &matches[1] // Capture secret name if it exists | ||
| } | ||
|
|
||
| list_secrets_req := ocivault.ListSecretsRequest{ | ||
| CompartmentId: common.String(oci.compartmentId), | ||
| SortBy: ocivault.ListSecretsSortByName, | ||
| VaultId: common.String(oci.vaultId), | ||
| Name: secretName, | ||
| Limit: common.Int(100), | ||
| LifecycleState: ocivault.SecretSummaryLifecycleStateActive, | ||
| SortOrder: ocivault.ListSecretsSortOrderDesc} | ||
|
|
||
| listSecretsFunc := func(request ocivault.ListSecretsRequest) (ocivault.ListSecretsResponse, error) { | ||
| return oci.vaultClient.ListSecrets(context.Background(), request) | ||
| } | ||
|
|
||
| data := make(map[string]interface{}) | ||
|
|
||
| for r, err := listSecretsFunc(list_secrets_req); ; r, err = listSecretsFunc(list_secrets_req) { | ||
| helpers.FatalIfError(err) | ||
|
|
||
| for _, secret := range r.Items { | ||
| req := ocism.GetSecretBundleByNameRequest{ | ||
| VaultId: common.String(oci.vaultId), | ||
| SecretName: common.String(*secret.SecretName)} | ||
|
|
||
| if version != "" && !strings.EqualFold(version, "latest") { | ||
| isPositiveInteger := OCISecretVersion.MatchString(version) | ||
| if !isPositiveInteger { | ||
| return nil, fmt.Errorf("version string must contain only positive integers") | ||
| } | ||
| secret_version, err := strconv.ParseInt(version, 10, 64) | ||
| helpers.FatalIfError(err) | ||
|
|
||
| list_secret_version_req := ocivault.ListSecretVersionsRequest{ | ||
| SecretId: common.String(*secret.Id), | ||
| SortBy: ocivault.ListSecretVersionsSortByVersionNumber, | ||
| SortOrder: ocivault.ListSecretVersionsSortOrderAsc, | ||
| Limit: common.Int(100)} | ||
|
|
||
| version_found,err := oci.CheckSecretVersion(list_secret_version_req,secret_version) | ||
| helpers.FatalIfError(err) | ||
| if version_found { | ||
| req.VersionNumber = common.Int64(secret_version) | ||
| } else{ | ||
| req.Stage = ocism.GetSecretBundleByNameStageLatest | ||
| } | ||
| } else { | ||
| req.Stage = ocism.GetSecretBundleByNameStageLatest | ||
| } | ||
|
|
||
| resp, err := oci.secretClient.GetSecretBundleByName(context.Background(), req) | ||
| helpers.FatalIfError(err) | ||
|
|
||
| secretContent := resp.SecretBundle.SecretBundleContent.(ocism.Base64SecretBundleContentDetails) | ||
| encodedSecret := *secretContent.Content | ||
|
|
||
| data[*secret.SecretName] = string(encodedSecret) | ||
| } | ||
|
|
||
| if r.OpcNextPage != nil { | ||
| // if there are more items in next page, fetch items from next page | ||
| list_secrets_req.Page = r.OpcNextPage | ||
| } else { | ||
| // no more result, break the loop | ||
| break | ||
| } | ||
| } | ||
|
|
||
| return data, nil | ||
| } | ||
|
|
||
|
|
||
| // GetIndividualSecret will get the specific secret (placeholder) from the SM backend | ||
| // For OCI Vault, the path is of format `ocivault/secretname` | ||
| // So, we use GetSecrets and extract the specific placeholder we want | ||
| func (oci *OCIVault) GetIndividualSecret(kvpath, secret, version string, annotations map[string]string) (interface{}, error) { | ||
| secretpath := kvpath + "/" + secret | ||
| data, err := oci.GetSecrets(secretpath, version, annotations) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| return data[secret], nil | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.