sops/azkv: drop fork of keysource implementation
As the forked code has been contributed upstream in a modified format. We continue to inject our own default credentials in the key server if none are provided by the Kustomization, to ensure we do not shell out to `az`. Signed-off-by: Hidde Beydals <hidde@hhh.computer>
This commit is contained in:
parent
2e50f41755
commit
1854a9f9dd
2
go.mod
2
go.mod
|
|
@ -14,7 +14,6 @@ require (
|
|||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.1
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.1
|
||||
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.0
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.13.35
|
||||
github.com/cyphar/filepath-securejoin v0.2.3
|
||||
github.com/dimchansky/utfbom v1.1.1
|
||||
|
|
@ -66,6 +65,7 @@ require (
|
|||
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
||||
cloud.google.com/go/iam v1.1.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0 // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1 // indirect
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import (
|
|||
"github.com/getsops/sops/v3"
|
||||
"github.com/getsops/sops/v3/aes"
|
||||
"github.com/getsops/sops/v3/age"
|
||||
"github.com/getsops/sops/v3/azkv"
|
||||
"github.com/getsops/sops/v3/cmd/sops/common"
|
||||
"github.com/getsops/sops/v3/cmd/sops/formats"
|
||||
"github.com/getsops/sops/v3/keyservice"
|
||||
|
|
@ -50,7 +51,7 @@ import (
|
|||
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1"
|
||||
intawskms "github.com/fluxcd/kustomize-controller/internal/sops/awskms"
|
||||
"github.com/fluxcd/kustomize-controller/internal/sops/azkv"
|
||||
intazkv "github.com/fluxcd/kustomize-controller/internal/sops/azkv"
|
||||
intkeyservice "github.com/fluxcd/kustomize-controller/internal/sops/keyservice"
|
||||
"github.com/fluxcd/kustomize-controller/internal/sops/pgp"
|
||||
)
|
||||
|
|
@ -141,7 +142,7 @@ type Decryptor struct {
|
|||
awsCredsProvider *awskms.CredentialsProvider
|
||||
// azureToken is the Azure credential token used to authenticate towards
|
||||
// any Azure Key Vault.
|
||||
azureToken *azkv.Token
|
||||
azureToken *azkv.TokenCredential
|
||||
// gcpCredsJSON is the JSON credential file of the service account used to
|
||||
// authenticate towards any GCP KMS.
|
||||
gcpCredsJSON []byte
|
||||
|
|
@ -244,13 +245,15 @@ func (d *Decryptor) ImportKeys(ctx context.Context) error {
|
|||
case filepath.Ext(DecryptionAzureAuthFile):
|
||||
// Make sure we have the absolute name
|
||||
if name == DecryptionAzureAuthFile {
|
||||
conf := azkv.AADConfig{}
|
||||
if err = azkv.LoadAADConfigFromBytes(value, &conf); err != nil {
|
||||
conf := intazkv.AADConfig{}
|
||||
if err = intazkv.LoadAADConfigFromBytes(value, &conf); err != nil {
|
||||
return fmt.Errorf("failed to import '%s' data from %s decryption Secret '%s': %w", name, provider, secretName, err)
|
||||
}
|
||||
if d.azureToken, err = azkv.TokenFromAADConfig(conf); err != nil {
|
||||
azureToken, err := intazkv.TokenCredentialFromAADConfig(conf)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to import '%s' data from %s decryption Secret '%s': %w", name, provider, secretName, err)
|
||||
}
|
||||
d.azureToken = azkv.NewTokenCredential(azureToken)
|
||||
}
|
||||
case filepath.Ext(DecryptionGCPCredsFile):
|
||||
if name == DecryptionGCPCredsFile {
|
||||
|
|
@ -554,19 +557,19 @@ func (d *Decryptor) sopsEncryptWithFormat(metadata sops.Metadata, data []byte, i
|
|||
}
|
||||
|
||||
// keyServiceServer returns the SOPS (local) key service clients used to serve
|
||||
// decryption requests. loadKeyServiceServers() is only configured on the first
|
||||
// decryption requests. loadKeyServiceServer() is only configured on the first
|
||||
// call.
|
||||
func (d *Decryptor) keyServiceServer() []keyservice.KeyServiceClient {
|
||||
d.localServiceOnce.Do(func() {
|
||||
d.loadKeyServiceServers()
|
||||
d.loadKeyServiceServer()
|
||||
})
|
||||
return d.keyServices
|
||||
}
|
||||
|
||||
// loadKeyServiceServers loads the SOPS (local) key service clients used to
|
||||
// loadKeyServiceServer loads the SOPS (local) key service clients used to
|
||||
// serve decryption requests for the current set of Decryptor
|
||||
// credentials.
|
||||
func (d *Decryptor) loadKeyServiceServers() {
|
||||
func (d *Decryptor) loadKeyServiceServer() {
|
||||
serverOpts := []intkeyservice.ServerOption{
|
||||
intkeyservice.WithGnuPGHome(d.gnuPGHome),
|
||||
intkeyservice.WithVaultToken(d.vaultToken),
|
||||
|
|
|
|||
|
|
@ -1,16 +1,32 @@
|
|||
// Copyright (C) 2022 The Flux authors
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
/*
|
||||
Copyright 2023 The Flux authors
|
||||
|
||||
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
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package azkv
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"unicode/utf16"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
|
||||
"github.com/dimchansky/utfbom"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
|
|
@ -49,7 +65,7 @@ type AZConfig struct {
|
|||
Password string `json:"password,omitempty"`
|
||||
}
|
||||
|
||||
// TokenFromAADConfig attempts to construct a Token using the AADConfig values.
|
||||
// TokenCredentialFromAADConfig attempts to construct a Token using the AADConfig values.
|
||||
// It detects credentials in the following order:
|
||||
//
|
||||
// - azidentity.ClientSecretCredential when `tenantId`, `clientId` and
|
||||
|
|
@ -63,53 +79,40 @@ type AZConfig struct {
|
|||
//
|
||||
// If no set of credentials is found or the azcore.TokenCredential can not be
|
||||
// created, an error is returned.
|
||||
func TokenFromAADConfig(c AADConfig) (_ *Token, err error) {
|
||||
var token azcore.TokenCredential
|
||||
func TokenCredentialFromAADConfig(c AADConfig) (token azcore.TokenCredential, err error) {
|
||||
if c.TenantID != "" && c.ClientID != "" {
|
||||
if c.ClientSecret != "" {
|
||||
if token, err = azidentity.NewClientSecretCredential(c.TenantID, c.ClientID, c.ClientSecret, &azidentity.ClientSecretCredentialOptions{
|
||||
return azidentity.NewClientSecretCredential(c.TenantID, c.ClientID, c.ClientSecret, &azidentity.ClientSecretCredentialOptions{
|
||||
ClientOptions: azcore.ClientOptions{
|
||||
Cloud: c.GetCloudConfig(),
|
||||
},
|
||||
}); err != nil {
|
||||
return
|
||||
}
|
||||
return NewToken(token), nil
|
||||
})
|
||||
}
|
||||
if c.ClientCertificate != "" {
|
||||
certs, pk, err := azidentity.ParseCertificates([]byte(c.ClientCertificate), []byte(c.ClientCertificatePassword))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if token, err = azidentity.NewClientCertificateCredential(c.TenantID, c.ClientID, certs, pk, &azidentity.ClientCertificateCredentialOptions{
|
||||
return azidentity.NewClientCertificateCredential(c.TenantID, c.ClientID, certs, pk, &azidentity.ClientCertificateCredentialOptions{
|
||||
SendCertificateChain: c.ClientCertificateSendChain,
|
||||
ClientOptions: azcore.ClientOptions{
|
||||
Cloud: c.GetCloudConfig(),
|
||||
},
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewToken(token), nil
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
switch {
|
||||
case c.Tenant != "" && c.AppID != "" && c.Password != "":
|
||||
if token, err = azidentity.NewClientSecretCredential(c.Tenant, c.AppID, c.Password, &azidentity.ClientSecretCredentialOptions{
|
||||
return azidentity.NewClientSecretCredential(c.Tenant, c.AppID, c.Password, &azidentity.ClientSecretCredentialOptions{
|
||||
ClientOptions: azcore.ClientOptions{
|
||||
Cloud: c.GetCloudConfig(),
|
||||
},
|
||||
}); err != nil {
|
||||
return
|
||||
}
|
||||
return NewToken(token), nil
|
||||
})
|
||||
case c.ClientID != "":
|
||||
if token, err = azidentity.NewManagedIdentityCredential(&azidentity.ManagedIdentityCredentialOptions{
|
||||
return azidentity.NewManagedIdentityCredential(&azidentity.ManagedIdentityCredentialOptions{
|
||||
ID: azidentity.ClientID(c.ClientID),
|
||||
}); err != nil {
|
||||
return
|
||||
}
|
||||
return NewToken(token), nil
|
||||
})
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid data: requires a '%s' field, a combination of '%s', '%s' and '%s', or '%s', '%s' and '%s'",
|
||||
"clientId", "tenantId", "clientId", "clientSecret", "tenantId", "clientId", "clientCertificate")
|
||||
|
|
@ -127,3 +130,24 @@ func (s AADConfig) GetCloudConfig() cloud.Configuration {
|
|||
}
|
||||
return cloud.AzurePublic
|
||||
}
|
||||
|
||||
func decode(b []byte) ([]byte, error) {
|
||||
reader, enc := utfbom.Skip(bytes.NewReader(b))
|
||||
switch enc {
|
||||
case utfbom.UTF16LittleEndian:
|
||||
u16 := make([]uint16, (len(b)/2)-1)
|
||||
err := binary.Read(reader, binary.LittleEndian, &u16)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []byte(string(utf16.Decode(u16))), nil
|
||||
case utfbom.UTF16BigEndian:
|
||||
u16 := make([]uint16, (len(b)/2)-1)
|
||||
err := binary.Read(reader, binary.BigEndian, &u16)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []byte(string(utf16.Decode(u16))), nil
|
||||
}
|
||||
return io.ReadAll(reader)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,18 @@
|
|||
// Copyright (C) 2022 The Flux authors
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
/*
|
||||
Copyright 2023 The Flux authors
|
||||
|
||||
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
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package azkv
|
||||
|
||||
|
|
@ -148,16 +158,16 @@ func TestTokenFromAADConfig(t *testing.T) {
|
|||
t.Run(tt.name, func(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
|
||||
got, err := TokenFromAADConfig(tt.config)
|
||||
got, err := TokenCredentialFromAADConfig(tt.config)
|
||||
if tt.wantErr {
|
||||
g.Expect(err).To(HaveOccurred())
|
||||
g.Expect(got.token).To(BeNil())
|
||||
g.Expect(got).To(BeNil())
|
||||
return
|
||||
}
|
||||
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
g.Expect(got.token).ToNot(BeNil())
|
||||
g.Expect(got.token).To(BeAssignableToTypeOf(tt.want))
|
||||
g.Expect(got).ToNot(BeNil())
|
||||
g.Expect(got).To(BeAssignableToTypeOf(tt.want))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
Copyright 2023 The Flux authors
|
||||
|
||||
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
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package azkv
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
|
||||
)
|
||||
|
||||
// DefaultTokenCredential is a modification of azidentity.NewDefaultAzureCredential,
|
||||
// specifically adapted to not shell out to the Azure CLI.
|
||||
//
|
||||
// It attempts to return an azcore.TokenCredential based on the following order:
|
||||
//
|
||||
// - azidentity.NewEnvironmentCredential if environment variables AZURE_CLIENT_ID,
|
||||
// AZURE_CLIENT_ID is set with either one of the following: (AZURE_CLIENT_SECRET)
|
||||
// or (AZURE_CLIENT_CERTIFICATE_PATH and AZURE_CLIENT_CERTIFICATE_PATH) or
|
||||
// (AZURE_USERNAME, AZURE_PASSWORD)
|
||||
// - azidentity.WorkloadIdentityCredential if environment variable configuration
|
||||
// (AZURE_AUTHORITY_HOST, AZURE_CLIENT_ID, AZURE_FEDERATED_TOKEN_FILE, AZURE_TENANT_ID)
|
||||
// is set by the Azure workload identity webhook.
|
||||
// - azidentity.ManagedIdentityCredential if only AZURE_CLIENT_ID env variable is set.
|
||||
func DefaultTokenCredential() (azcore.TokenCredential, error) {
|
||||
var (
|
||||
azureClientID = "AZURE_CLIENT_ID"
|
||||
azureFederatedTokenFile = "AZURE_FEDERATED_TOKEN_FILE"
|
||||
azureAuthorityHost = "AZURE_AUTHORITY_HOST"
|
||||
azureTenantID = "AZURE_TENANT_ID"
|
||||
)
|
||||
|
||||
var errorMessages []string
|
||||
options := &azidentity.DefaultAzureCredentialOptions{}
|
||||
|
||||
envCred, err := azidentity.NewEnvironmentCredential(&azidentity.EnvironmentCredentialOptions{
|
||||
ClientOptions: options.ClientOptions, DisableInstanceDiscovery: options.DisableInstanceDiscovery},
|
||||
)
|
||||
if err == nil {
|
||||
return envCred, nil
|
||||
} else {
|
||||
errorMessages = append(errorMessages, "EnvironmentCredential: "+err.Error())
|
||||
}
|
||||
|
||||
// workload identity requires values for AZURE_AUTHORITY_HOST, AZURE_CLIENT_ID, AZURE_FEDERATED_TOKEN_FILE, AZURE_TENANT_ID
|
||||
haveWorkloadConfig := false
|
||||
clientID, haveClientID := os.LookupEnv(azureClientID)
|
||||
if haveClientID {
|
||||
if file, ok := os.LookupEnv(azureFederatedTokenFile); ok {
|
||||
if _, ok := os.LookupEnv(azureAuthorityHost); ok {
|
||||
if tenantID, ok := os.LookupEnv(azureTenantID); ok {
|
||||
haveWorkloadConfig = true
|
||||
workloadCred, err := azidentity.NewWorkloadIdentityCredential(&azidentity.WorkloadIdentityCredentialOptions{
|
||||
ClientID: clientID,
|
||||
TenantID: tenantID,
|
||||
TokenFilePath: file,
|
||||
ClientOptions: options.ClientOptions,
|
||||
DisableInstanceDiscovery: options.DisableInstanceDiscovery,
|
||||
})
|
||||
if err == nil {
|
||||
return workloadCred, nil
|
||||
} else {
|
||||
errorMessages = append(errorMessages, "Workload Identity"+": "+err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if !haveWorkloadConfig {
|
||||
err := errors.New("missing environment variables for workload identity. Check webhook and pod configuration")
|
||||
errorMessages = append(errorMessages, fmt.Sprintf("Workload Identity: %s", err))
|
||||
}
|
||||
|
||||
o := &azidentity.ManagedIdentityCredentialOptions{ClientOptions: options.ClientOptions}
|
||||
if haveClientID {
|
||||
o.ID = azidentity.ClientID(clientID)
|
||||
}
|
||||
miCred, err := azidentity.NewManagedIdentityCredential(o)
|
||||
if err == nil {
|
||||
return miCred, nil
|
||||
} else {
|
||||
errorMessages = append(errorMessages, "ManagedIdentity"+": "+err.Error())
|
||||
}
|
||||
|
||||
return nil, errors.New(strings.Join(errorMessages, "\n"))
|
||||
}
|
||||
|
|
@ -1,277 +0,0 @@
|
|||
// Copyright (C) 2022 The Flux authors
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
package azkv
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode/utf16"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys"
|
||||
"github.com/dimchansky/utfbom"
|
||||
)
|
||||
|
||||
var (
|
||||
// azkvTTL is the duration after which a MasterKey requires rotation.
|
||||
azkvTTL = time.Hour * 24 * 30 * 6
|
||||
)
|
||||
|
||||
// MasterKey is an Azure Key Vault Key used to Encrypt and Decrypt SOPS'
|
||||
// data key.
|
||||
//
|
||||
// The underlying authentication token can be configured using TokenFromAADConfig
|
||||
// and Token.ApplyToMasterKey().
|
||||
type MasterKey struct {
|
||||
VaultURL string
|
||||
Name string
|
||||
Version string
|
||||
|
||||
EncryptedKey string
|
||||
CreationDate time.Time
|
||||
|
||||
token azcore.TokenCredential
|
||||
}
|
||||
|
||||
// MasterKeyFromURL creates a new MasterKey from a Vault URL, key name, and key
|
||||
// version.
|
||||
func MasterKeyFromURL(url, name, version string) *MasterKey {
|
||||
key := &MasterKey{
|
||||
VaultURL: url,
|
||||
Name: name,
|
||||
Version: version,
|
||||
CreationDate: time.Now().UTC(),
|
||||
}
|
||||
return key
|
||||
}
|
||||
|
||||
// Token is an azcore.TokenCredential used for authenticating towards Azure Key
|
||||
// Vault.
|
||||
type Token struct {
|
||||
token azcore.TokenCredential
|
||||
}
|
||||
|
||||
// NewToken creates a new Token with the provided azcore.TokenCredential.
|
||||
func NewToken(token azcore.TokenCredential) *Token {
|
||||
return &Token{token: token}
|
||||
}
|
||||
|
||||
// ApplyToMasterKey configures the Token on the provided key.
|
||||
func (t Token) ApplyToMasterKey(key *MasterKey) {
|
||||
key.token = t.token
|
||||
}
|
||||
|
||||
// Encrypt takes a SOPS data key, encrypts it with Azure Key Vault, and stores
|
||||
// the result in the EncryptedKey field.
|
||||
func (key *MasterKey) Encrypt(dataKey []byte) error {
|
||||
creds, err := key.getTokenCredential()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get Azure token credential to encrypt: %w", err)
|
||||
}
|
||||
c, err := azkeys.NewClient(key.VaultURL, creds, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to construct Azure Key Vault crypto client to encrypt data: %w", err)
|
||||
}
|
||||
resp, err := c.Encrypt(context.Background(), key.Name, key.Version, azkeys.KeyOperationParameters{
|
||||
Algorithm: to.Ptr(azkeys.EncryptionAlgorithmRSAOAEP256),
|
||||
Value: dataKey,
|
||||
}, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to encrypt sops data key with Azure Key Vault key '%s': %w", key.ToString(), err)
|
||||
}
|
||||
// This is for compatibility between the SOPS upstream which uses
|
||||
// a much older Azure SDK, and our implementation which is up-to-date
|
||||
// with the latest.
|
||||
encodedEncryptedKey := base64.RawURLEncoding.EncodeToString(resp.Result)
|
||||
key.SetEncryptedDataKey([]byte(encodedEncryptedKey))
|
||||
return nil
|
||||
}
|
||||
|
||||
// EncryptedDataKey returns the encrypted data key this master key holds.
|
||||
func (key *MasterKey) EncryptedDataKey() []byte {
|
||||
return []byte(key.EncryptedKey)
|
||||
}
|
||||
|
||||
// SetEncryptedDataKey sets the encrypted data key for this master key.
|
||||
func (key *MasterKey) SetEncryptedDataKey(enc []byte) {
|
||||
key.EncryptedKey = string(enc)
|
||||
}
|
||||
|
||||
// EncryptIfNeeded encrypts the provided SOPS data key, if it has not been
|
||||
// encrypted yet.
|
||||
func (key *MasterKey) EncryptIfNeeded(dataKey []byte) error {
|
||||
if key.EncryptedKey == "" {
|
||||
return key.Encrypt(dataKey)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Decrypt decrypts the EncryptedKey field with Azure Key Vault and returns
|
||||
// the result.
|
||||
func (key *MasterKey) Decrypt() ([]byte, error) {
|
||||
creds, err := key.getTokenCredential()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get Azure token credential to decrypt: %w", err)
|
||||
}
|
||||
c, err := azkeys.NewClient(key.VaultURL, creds, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to construct Azure Key Vault crypto client to decrypt data: %w", err)
|
||||
}
|
||||
// This is for compatibility between the SOPS upstream which uses
|
||||
// a much older Azure SDK, and our implementation which is up-to-date
|
||||
// with the latest.
|
||||
rawEncryptedKey, err := base64.RawURLEncoding.DecodeString(key.EncryptedKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to base64 decode Azure Key Vault encrypted key: %w", err)
|
||||
}
|
||||
resp, err := c.Decrypt(context.Background(), key.Name, key.Version, azkeys.KeyOperationParameters{
|
||||
Algorithm: to.Ptr(azkeys.EncryptionAlgorithmRSAOAEP256),
|
||||
Value: rawEncryptedKey,
|
||||
}, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to decrypt sops data key with Azure Key Vault key '%s': %w", key.ToString(), err)
|
||||
}
|
||||
return resp.Result, nil
|
||||
}
|
||||
|
||||
// NeedsRotation returns whether the data key needs to be rotated or not.
|
||||
func (key *MasterKey) NeedsRotation() bool {
|
||||
return time.Since(key.CreationDate) > (azkvTTL)
|
||||
}
|
||||
|
||||
// ToString converts the key to a string representation.
|
||||
func (key *MasterKey) ToString() string {
|
||||
return fmt.Sprintf("%s/keys/%s/%s", key.VaultURL, key.Name, key.Version)
|
||||
}
|
||||
|
||||
// ToMap converts the MasterKey to a map for serialization purposes.
|
||||
func (key MasterKey) ToMap() map[string]interface{} {
|
||||
out := make(map[string]interface{})
|
||||
out["vaultUrl"] = key.VaultURL
|
||||
out["key"] = key.Name
|
||||
out["version"] = key.Version
|
||||
out["created_at"] = key.CreationDate.UTC().Format(time.RFC3339)
|
||||
out["enc"] = key.EncryptedKey
|
||||
return out
|
||||
}
|
||||
|
||||
func decode(b []byte) ([]byte, error) {
|
||||
reader, enc := utfbom.Skip(bytes.NewReader(b))
|
||||
switch enc {
|
||||
case utfbom.UTF16LittleEndian:
|
||||
u16 := make([]uint16, (len(b)/2)-1)
|
||||
err := binary.Read(reader, binary.LittleEndian, &u16)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []byte(string(utf16.Decode(u16))), nil
|
||||
case utfbom.UTF16BigEndian:
|
||||
u16 := make([]uint16, (len(b)/2)-1)
|
||||
err := binary.Read(reader, binary.BigEndian, &u16)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []byte(string(utf16.Decode(u16))), nil
|
||||
}
|
||||
return ioutil.ReadAll(reader)
|
||||
}
|
||||
|
||||
// getTokenCredential returns the tokenCredential of the MasterKey, or
|
||||
// azidentity.NewDefaultAzureCredential.
|
||||
func (key *MasterKey) getTokenCredential() (azcore.TokenCredential, error) {
|
||||
if key.token == nil {
|
||||
return getDefaultAzureCredential()
|
||||
}
|
||||
return key.token, nil
|
||||
}
|
||||
|
||||
// getDefaultAzureCredentials is a modification of
|
||||
// azidentity.NewDefaultAzureCredential, specifically adapted to not shell out
|
||||
// to the Azure CLI.
|
||||
//
|
||||
// It attemps to return an azcore.TokenCredential based on the following order:
|
||||
//
|
||||
// - azidentity.NewEnvironmentCredential if environment variables AZURE_CLIENT_ID,
|
||||
// AZURE_CLIENT_ID is set with either one of the following: (AZURE_CLIENT_SECRET)
|
||||
// or (AZURE_CLIENT_CERTIFICATE_PATH and AZURE_CLIENT_CERTIFICATE_PATH) or
|
||||
// (AZURE_USERNAME, AZURE_PASSWORD)
|
||||
// - azidentity.WorkloadIdentity if environment variable configuration
|
||||
// (AZURE_AUTHORITY_HOST, AZURE_CLIENT_ID, AZURE_FEDERATED_TOKEN_FILE, AZURE_TENANT_ID)
|
||||
// is set by the Azure workload identity webhook.
|
||||
// - azidentity.ManagedIdentity if only AZURE_CLIENT_ID env variable is set.
|
||||
func getDefaultAzureCredential() (azcore.TokenCredential, error) {
|
||||
var (
|
||||
azureClientID = "AZURE_CLIENT_ID"
|
||||
azureFederatedTokenFile = "AZURE_FEDERATED_TOKEN_FILE"
|
||||
azureAuthorityHost = "AZURE_AUTHORITY_HOST"
|
||||
azureTenantID = "AZURE_TENANT_ID"
|
||||
)
|
||||
|
||||
var errorMessages []string
|
||||
options := &azidentity.DefaultAzureCredentialOptions{}
|
||||
|
||||
envCred, err := azidentity.NewEnvironmentCredential(&azidentity.EnvironmentCredentialOptions{
|
||||
ClientOptions: options.ClientOptions, DisableInstanceDiscovery: options.DisableInstanceDiscovery},
|
||||
)
|
||||
if err == nil {
|
||||
return envCred, nil
|
||||
} else {
|
||||
errorMessages = append(errorMessages, "EnvironmentCredential: "+err.Error())
|
||||
}
|
||||
|
||||
// workload identity requires values for AZURE_AUTHORITY_HOST, AZURE_CLIENT_ID, AZURE_FEDERATED_TOKEN_FILE, AZURE_TENANT_ID
|
||||
haveWorkloadConfig := false
|
||||
clientID, haveClientID := os.LookupEnv(azureClientID)
|
||||
if haveClientID {
|
||||
if file, ok := os.LookupEnv(azureFederatedTokenFile); ok {
|
||||
if _, ok := os.LookupEnv(azureAuthorityHost); ok {
|
||||
if tenantID, ok := os.LookupEnv(azureTenantID); ok {
|
||||
haveWorkloadConfig = true
|
||||
workloadCred, err := azidentity.NewWorkloadIdentityCredential(&azidentity.WorkloadIdentityCredentialOptions{
|
||||
ClientID: clientID,
|
||||
TenantID: tenantID,
|
||||
TokenFilePath: file,
|
||||
ClientOptions: options.ClientOptions,
|
||||
DisableInstanceDiscovery: options.DisableInstanceDiscovery,
|
||||
})
|
||||
if err == nil {
|
||||
return workloadCred, nil
|
||||
} else {
|
||||
errorMessages = append(errorMessages, "Workload Identity"+": "+err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if !haveWorkloadConfig {
|
||||
err := errors.New("missing environment variables for workload identity. Check webhook and pod configuration")
|
||||
errorMessages = append(errorMessages, fmt.Sprintf("Workload Identity: %s", err))
|
||||
}
|
||||
|
||||
o := &azidentity.ManagedIdentityCredentialOptions{ClientOptions: options.ClientOptions}
|
||||
if haveClientID {
|
||||
o.ID = azidentity.ClientID(clientID)
|
||||
}
|
||||
miCred, err := azidentity.NewManagedIdentityCredential(o)
|
||||
if err == nil {
|
||||
return miCred, nil
|
||||
} else {
|
||||
errorMessages = append(errorMessages, "ManagedIdentity"+": "+err.Error())
|
||||
}
|
||||
|
||||
return nil, errors.New(strings.Join(errorMessages, "\n"))
|
||||
}
|
||||
|
|
@ -1,147 +0,0 @@
|
|||
//go:build integration
|
||||
// +build integration
|
||||
|
||||
// Copyright (C) 2022 The Flux authors
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
package azkv
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys"
|
||||
"github.com/getsops/sops/v3/azkv"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
// The following values should be created based on the instructions in:
|
||||
// https://github.com/mozilla/sops#encrypting-using-azure-key-vault
|
||||
var (
|
||||
testVaultURL = os.Getenv("TEST_AZURE_VAULT_URL")
|
||||
testVaultKeyName = os.Getenv("TEST_AZURE_VAULT_KEY_NAME")
|
||||
testVaultKeyVersion = os.Getenv("TEST_AZURE_VAULT_KEY_VERSION")
|
||||
testAADConfig = AADConfig{
|
||||
TenantID: os.Getenv("TEST_AZURE_TENANT_ID"),
|
||||
ClientID: os.Getenv("TEST_AZURE_CLIENT_ID"),
|
||||
ClientSecret: os.Getenv("TEST_AZURE_CLIENT_SECRET"),
|
||||
}
|
||||
)
|
||||
|
||||
func TestMasterKey_Encrypt(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
|
||||
key := MasterKeyFromURL(testVaultURL, testVaultKeyName, testVaultKeyVersion)
|
||||
token, err := TokenFromAADConfig(testAADConfig)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
token.ApplyToMasterKey(key)
|
||||
|
||||
g.Expect(key.Encrypt([]byte("foo"))).To(Succeed())
|
||||
g.Expect(key.EncryptedDataKey()).ToNot(BeEmpty())
|
||||
}
|
||||
|
||||
func TestMasterKey_Decrypt(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
|
||||
key := MasterKeyFromURL(testVaultURL, testVaultKeyName, testVaultKeyVersion)
|
||||
token, err := TokenFromAADConfig(testAADConfig)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
token.ApplyToMasterKey(key)
|
||||
|
||||
dataKey := []byte("this is super secret data")
|
||||
c, err := azkeys.NewClient(key.VaultURL, key.token, nil)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
resp, err := c.Encrypt(context.Background(), key.Name, key.Version, azkeys.KeyOperationParameters{
|
||||
Algorithm: to.Ptr(azkeys.EncryptionAlgorithmRSAOAEP256),
|
||||
Value: dataKey,
|
||||
}, nil)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
key.EncryptedKey = base64.RawURLEncoding.EncodeToString(resp.Result)
|
||||
g.Expect(key.EncryptedKey).ToNot(BeEmpty())
|
||||
g.Expect(key.EncryptedKey).ToNot(Equal(dataKey))
|
||||
|
||||
got, err := key.Decrypt()
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
g.Expect(got).To(Equal(dataKey))
|
||||
}
|
||||
|
||||
func TestMasterKey_EncryptDecrypt_RoundTrip(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
|
||||
key := MasterKeyFromURL(testVaultURL, testVaultKeyName, testVaultKeyVersion)
|
||||
token, err := TokenFromAADConfig(testAADConfig)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
token.ApplyToMasterKey(key)
|
||||
|
||||
dataKey := []byte("some-data-that-should-be-secret")
|
||||
|
||||
g.Expect(key.Encrypt(dataKey)).To(Succeed())
|
||||
g.Expect(key.EncryptedDataKey()).ToNot(BeEmpty())
|
||||
|
||||
dec, err := key.Decrypt()
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
g.Expect(dec).To(Equal(dataKey))
|
||||
}
|
||||
|
||||
func TestMasterKey_Encrypt_SOPS_Compat(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
|
||||
encryptKey := MasterKeyFromURL(testVaultURL, testVaultKeyName, testVaultKeyVersion)
|
||||
token, err := TokenFromAADConfig(testAADConfig)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
token.ApplyToMasterKey(encryptKey)
|
||||
|
||||
dataKey := []byte("foo")
|
||||
g.Expect(encryptKey.Encrypt(dataKey)).To(Succeed())
|
||||
|
||||
t.Setenv("AZURE_CLIENT_ID", testAADConfig.ClientID)
|
||||
t.Setenv("AZURE_TENANT_ID", testAADConfig.TenantID)
|
||||
t.Setenv("AZURE_CLIENT_SECRET", testAADConfig.ClientSecret)
|
||||
|
||||
decryptKey := &azkv.MasterKey{
|
||||
VaultURL: testVaultURL,
|
||||
Name: testVaultKeyName,
|
||||
Version: testVaultKeyVersion,
|
||||
EncryptedKey: encryptKey.EncryptedKey,
|
||||
CreationDate: time.Now(),
|
||||
}
|
||||
|
||||
dec, err := decryptKey.Decrypt()
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
g.Expect(dec).To(Equal(dataKey))
|
||||
}
|
||||
|
||||
func TestMasterKey_Decrypt_SOPS_Compat(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
|
||||
t.Setenv("AZURE_CLIENT_ID", testAADConfig.ClientID)
|
||||
t.Setenv("AZURE_TENANT_ID", testAADConfig.TenantID)
|
||||
t.Setenv("AZURE_CLIENT_SECRET", testAADConfig.ClientSecret)
|
||||
|
||||
dataKey := []byte("foo")
|
||||
|
||||
encryptKey := &azkv.MasterKey{
|
||||
VaultURL: testVaultURL,
|
||||
Name: testVaultKeyName,
|
||||
Version: testVaultKeyVersion,
|
||||
CreationDate: time.Now(),
|
||||
}
|
||||
g.Expect(encryptKey.Encrypt(dataKey)).To(Succeed())
|
||||
|
||||
decryptKey := MasterKeyFromURL(testVaultURL, testVaultKeyName, testVaultKeyVersion)
|
||||
token, err := TokenFromAADConfig(testAADConfig)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
token.ApplyToMasterKey(decryptKey)
|
||||
|
||||
decryptKey.EncryptedKey = encryptKey.EncryptedKey
|
||||
dec, err := decryptKey.Decrypt()
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
g.Expect(dec).To(Equal(dataKey))
|
||||
}
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
// Copyright (C) 2022 The Flux authors
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
package azkv
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
func TestToken_ApplyToMasterKey(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
|
||||
token, err := TokenFromAADConfig(
|
||||
AADConfig{TenantID: "tenant", ClientID: "client", ClientSecret: "secret"},
|
||||
)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
key := &MasterKey{}
|
||||
token.ApplyToMasterKey(key)
|
||||
g.Expect(key.token).To(Equal(token.token))
|
||||
}
|
||||
|
||||
func TestMasterKey_EncryptedDataKey(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
|
||||
key := &MasterKey{EncryptedKey: "some key"}
|
||||
g.Expect(key.EncryptedDataKey()).To(BeEquivalentTo(key.EncryptedKey))
|
||||
}
|
||||
|
||||
func TestMasterKey_SetEncryptedDataKey(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
|
||||
encryptedKey := []byte("encrypted")
|
||||
key := &MasterKey{}
|
||||
key.SetEncryptedDataKey(encryptedKey)
|
||||
g.Expect(key.EncryptedKey).To(BeEquivalentTo(encryptedKey))
|
||||
}
|
||||
|
||||
func TestMasterKey_NeedsRotation(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
|
||||
key := MasterKeyFromURL("", "", "")
|
||||
g.Expect(key.NeedsRotation()).To(BeFalse())
|
||||
|
||||
key.CreationDate = key.CreationDate.Add(-(azkvTTL + time.Second))
|
||||
g.Expect(key.NeedsRotation()).To(BeTrue())
|
||||
}
|
||||
|
||||
func TestMasterKey_ToString(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
|
||||
key := MasterKeyFromURL("https://myvault.vault.azure.net", "key-name", "key-version")
|
||||
g.Expect(key.ToString()).To(Equal("https://myvault.vault.azure.net/keys/key-name/key-version"))
|
||||
}
|
||||
|
||||
func TestMasterKey_ToMap(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
|
||||
key := MasterKeyFromURL("https://myvault.vault.azure.net", "key-name", "key-version")
|
||||
key.EncryptedKey = "data"
|
||||
g.Expect(key.ToMap()).To(Equal(map[string]interface{}{
|
||||
"vaultUrl": key.VaultURL,
|
||||
"key": key.Name,
|
||||
"version": key.Version,
|
||||
"created_at": key.CreationDate.UTC().Format(time.RFC3339),
|
||||
"enc": key.EncryptedKey,
|
||||
}))
|
||||
}
|
||||
|
|
@ -9,10 +9,10 @@ package keyservice
|
|||
import (
|
||||
extage "filippo.io/age"
|
||||
"github.com/getsops/sops/v3/age"
|
||||
"github.com/getsops/sops/v3/azkv"
|
||||
"github.com/getsops/sops/v3/keyservice"
|
||||
awskms "github.com/getsops/sops/v3/kms"
|
||||
|
||||
"github.com/fluxcd/kustomize-controller/internal/sops/azkv"
|
||||
"github.com/fluxcd/kustomize-controller/internal/sops/gcpkms"
|
||||
"github.com/fluxcd/kustomize-controller/internal/sops/hcvault"
|
||||
"github.com/fluxcd/kustomize-controller/internal/sops/pgp"
|
||||
|
|
@ -69,7 +69,7 @@ func (o WithGCPCredsJSON) ApplyToServer(s *Server) {
|
|||
|
||||
// WithAzureToken configures the Azure credential token on the Server.
|
||||
type WithAzureToken struct {
|
||||
Token *azkv.Token
|
||||
Token *azkv.TokenCredential
|
||||
}
|
||||
|
||||
// ApplyToServer applies this configuration to the given Server.
|
||||
|
|
|
|||
|
|
@ -10,11 +10,12 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/getsops/sops/v3/age"
|
||||
"github.com/getsops/sops/v3/azkv"
|
||||
"github.com/getsops/sops/v3/keyservice"
|
||||
awskms "github.com/getsops/sops/v3/kms"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/fluxcd/kustomize-controller/internal/sops/azkv"
|
||||
intazkv "github.com/fluxcd/kustomize-controller/internal/sops/azkv"
|
||||
"github.com/fluxcd/kustomize-controller/internal/sops/gcpkms"
|
||||
"github.com/fluxcd/kustomize-controller/internal/sops/hcvault"
|
||||
"github.com/fluxcd/kustomize-controller/internal/sops/pgp"
|
||||
|
|
@ -45,7 +46,7 @@ type Server struct {
|
|||
// azureToken is the credential token used for Encrypt and Decrypt
|
||||
// operations of Azure Key Vault requests.
|
||||
// When nil, the request will be handled by defaultServer.
|
||||
azureToken *azkv.Token
|
||||
azureToken *azkv.TokenCredential
|
||||
|
||||
// awsCredsProvider is the Credentials object used for Encrypt and Decrypt
|
||||
// operations of AWS KMS requests.
|
||||
|
|
@ -300,7 +301,15 @@ func (ks *Server) encryptWithAzureKeyVault(key *keyservice.AzureKeyVaultKey, pla
|
|||
Name: key.Name,
|
||||
Version: key.Version,
|
||||
}
|
||||
if ks.azureToken != nil {
|
||||
if ks.azureToken == nil {
|
||||
// Ensure we use the default token credential if none is provided
|
||||
// _without_ shelling out to `az`.
|
||||
defaultToken, err := intazkv.DefaultTokenCredential()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get Azure token credential to encrypt data: %w", err)
|
||||
}
|
||||
azkv.NewTokenCredential(defaultToken).ApplyToMasterKey(&azureKey)
|
||||
} else {
|
||||
ks.azureToken.ApplyToMasterKey(&azureKey)
|
||||
}
|
||||
if err := azureKey.Encrypt(plaintext); err != nil {
|
||||
|
|
@ -315,7 +324,15 @@ func (ks *Server) decryptWithAzureKeyVault(key *keyservice.AzureKeyVaultKey, cip
|
|||
Name: key.Name,
|
||||
Version: key.Version,
|
||||
}
|
||||
if ks.azureToken != nil {
|
||||
if ks.azureToken == nil {
|
||||
// Ensure we use the default token credential if none is provided
|
||||
// _without_ shelling out to `az`.
|
||||
defaultToken, err := intazkv.DefaultTokenCredential()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get Azure token credential to decrypt data: %w", err)
|
||||
}
|
||||
azkv.NewTokenCredential(defaultToken).ApplyToMasterKey(&azureKey)
|
||||
} else {
|
||||
ks.azureToken.ApplyToMasterKey(&azureKey)
|
||||
}
|
||||
azureKey.EncryptedKey = string(ciphertext)
|
||||
|
|
|
|||
|
|
@ -14,12 +14,12 @@ import (
|
|||
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
|
||||
"github.com/aws/aws-sdk-go-v2/credentials"
|
||||
"github.com/getsops/sops/v3/age"
|
||||
"github.com/getsops/sops/v3/azkv"
|
||||
"github.com/getsops/sops/v3/keyservice"
|
||||
awskms "github.com/getsops/sops/v3/kms"
|
||||
. "github.com/onsi/gomega"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/fluxcd/kustomize-controller/internal/sops/azkv"
|
||||
"github.com/fluxcd/kustomize-controller/internal/sops/gcpkms"
|
||||
"github.com/fluxcd/kustomize-controller/internal/sops/hcvault"
|
||||
"github.com/fluxcd/kustomize-controller/internal/sops/pgp"
|
||||
|
|
@ -164,9 +164,9 @@ func TestServer_EncryptDecrypt_azkv(t *testing.T) {
|
|||
|
||||
identity, err := azidentity.NewDefaultAzureCredential(nil)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
s := NewServer(WithAzureToken{Token: azkv.NewToken(identity)})
|
||||
s := NewServer(WithAzureToken{Token: azkv.NewTokenCredential(identity)})
|
||||
|
||||
key := KeyFromMasterKey(azkv.MasterKeyFromURL("", "", ""))
|
||||
key := KeyFromMasterKey(azkv.NewMasterKey("", "", ""))
|
||||
_, err = s.Encrypt(context.TODO(), &keyservice.EncryptRequest{
|
||||
Key: &key,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -11,11 +11,11 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/getsops/sops/v3/age"
|
||||
"github.com/getsops/sops/v3/azkv"
|
||||
"github.com/getsops/sops/v3/keys"
|
||||
"github.com/getsops/sops/v3/keyservice"
|
||||
awskms "github.com/getsops/sops/v3/kms"
|
||||
|
||||
"github.com/fluxcd/kustomize-controller/internal/sops/azkv"
|
||||
"github.com/fluxcd/kustomize-controller/internal/sops/gcpkms"
|
||||
"github.com/fluxcd/kustomize-controller/internal/sops/hcvault"
|
||||
"github.com/fluxcd/kustomize-controller/internal/sops/pgp"
|
||||
|
|
|
|||
Loading…
Reference in New Issue