97 lines
3.3 KiB
Go
97 lines
3.3 KiB
Go
package secrets
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
secretcontracts "git.cin.su/m/Assistant/contracts/secrets"
|
|
)
|
|
|
|
func TestMachineCredentialEnsureIsIdempotentAndKeepsValueOutOfMetadata(t *testing.T) {
|
|
now := time.Unix(1_700_000_000, 0)
|
|
store, err := NewLocalMachineCredentialStore(t.TempDir(), -1, -1, func() time.Time { return now })
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
first, err := store.Ensure(ControlPlaneServiceTokenSpec())
|
|
if err != nil || !first.Created || first.Metadata.Version != 1 {
|
|
t.Fatalf("first provision = %#v, %v", first, err)
|
|
}
|
|
second, err := store.Ensure(ControlPlaneServiceTokenSpec())
|
|
if err != nil || second.Created || second.Metadata.Version != 1 {
|
|
t.Fatalf("second provision = %#v, %v", second, err)
|
|
}
|
|
metadata, err := os.ReadFile(filepath.Join(store.metadata, ControlPlaneServiceTokenID+".json"))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
artifact, err := os.ReadFile(filepath.Join(store.root, ControlPlaneServiceTokenID))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if strings.Contains(string(metadata), strings.TrimSpace(string(artifact))) {
|
|
t.Fatal("metadata unexpectedly contains a credential value")
|
|
}
|
|
info, err := os.Stat(filepath.Join(store.root, ControlPlaneServiceTokenID))
|
|
if err != nil || (runtime.GOOS != "windows" && info.Mode().Perm() != 0o400) {
|
|
t.Fatalf("artifact mode = %v, %v", info.Mode(), err)
|
|
}
|
|
}
|
|
|
|
func TestMachineCredentialSpecSupportsMachineCredentialKinds(t *testing.T) {
|
|
cases := []MachineCredentialSpec{
|
|
ControlPlaneServiceTokenSpec(),
|
|
{ID: "database_role_password", Kind: MachineCredentialDatabaseRole, Purpose: secretcontracts.SecretPurposeDatabasePassword, Consumers: []secretcontracts.RuntimeConsumer{secretcontracts.RuntimeConsumerCore}, Bytes: 32},
|
|
{ID: "internal_api_credential", Kind: MachineCredentialInternalAPI, Purpose: secretcontracts.SecretPurposeServiceAuthentication, Consumers: []secretcontracts.RuntimeConsumer{secretcontracts.RuntimeConsumerCommit}, Bytes: 32},
|
|
}
|
|
for _, value := range cases {
|
|
if err := validateMachineCredentialSpec(value); err != nil {
|
|
t.Fatalf("credential kind %s is unsupported: %v", value.Kind, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestMachineCredentialRotateAtomicallyReplacesArtifactAndAdvancesVersion(t *testing.T) {
|
|
store, err := NewLocalMachineCredentialStore(t.TempDir(), -1, -1, time.Now)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := store.Ensure(ControlPlaneServiceTokenSpec()); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
path := filepath.Join(store.root, ControlPlaneServiceTokenID)
|
|
oldValue, err := os.ReadFile(path)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
rotated, err := store.Rotate(ControlPlaneServiceTokenSpec(), "exposure detected")
|
|
if err != nil || !rotated.Rotated || rotated.Metadata.Version != 2 {
|
|
t.Fatalf("rotation = %#v, %v", rotated, err)
|
|
}
|
|
newValue, err := os.ReadFile(path)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if string(oldValue) == string(newValue) {
|
|
t.Fatal("rotation retained old credential")
|
|
}
|
|
}
|
|
|
|
func TestMachineCredentialRejectsUnsafeExistingArtifact(t *testing.T) {
|
|
root := t.TempDir()
|
|
if err := os.Mkdir(filepath.Join(root, ControlPlaneServiceTokenID), 0o700); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
store, err := NewLocalMachineCredentialStore(root, -1, -1, time.Now)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := store.Ensure(ControlPlaneServiceTokenSpec()); err != ErrCredentialArtifactUnsafe {
|
|
t.Fatalf("unsafe artifact error = %v", err)
|
|
}
|
|
}
|