-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #17 from MGTheTrain/opt/general
Descriptive file names, VaultConnector implementation and tests, Key service implementation
- Loading branch information
Showing
27 changed files
with
566 additions
and
198 deletions.
There are no files selected for viewing
This file contains 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
File renamed without changes.
This file was deleted.
Oops, something went wrong.
This file contains 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,116 @@ | ||
package services | ||
|
||
import ( | ||
"crypto_vault_service/internal/domain/keys" | ||
"crypto_vault_service/internal/infrastructure/connector" | ||
"crypto_vault_service/internal/persistence/repository" | ||
"fmt" | ||
"time" | ||
|
||
"github.com/google/uuid" | ||
) | ||
|
||
type CryptKeyUploadService struct { | ||
VaultConnector connector.VaultConnector | ||
CryptoKeyRepo repository.CryptoKeyRepository | ||
} | ||
|
||
func (s *CryptKeyUploadService) Upload(filePaths []string) ([]*keys.CryptoKeyMeta, error) { | ||
// Step 1: Upload files to blob storage | ||
userId := uuid.New().String() | ||
blobMeta, err := s.VaultConnector.Upload(filePaths, userId) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to upload files: %w", err) | ||
} | ||
|
||
// Step 2: Store the metadata in the database | ||
var keyMetas []*keys.CryptoKeyMeta | ||
for _, blob := range blobMeta { | ||
// Map Blob metadata to CryptoKey metadata | ||
keyMeta := &keys.CryptoKeyMeta{ | ||
ID: uuid.New().String(), // Generate valid UUID for ID | ||
Type: "RSA", // Example key type | ||
DateTimeCreated: time.Now(), // Valid DateTimeCreated time | ||
UserID: uuid.New().String(), // Generate valid UUID for UserID | ||
} | ||
|
||
// Validate CryptoKeyMeta | ||
if err := keyMeta.Validate(); err != nil { | ||
return nil, fmt.Errorf("invalid key metadata: %w", err) | ||
} | ||
|
||
// Save metadata to DB | ||
if err := s.CryptoKeyRepo.Create(blob); err != nil { | ||
return nil, fmt.Errorf("failed to create metadata for key of type %s: %w", keyMeta.Type, err) | ||
} | ||
|
||
// Append to list | ||
keyMetas = append(keyMetas, keyMeta) | ||
} | ||
|
||
// Return metadata | ||
return keyMetas, nil | ||
} | ||
|
||
// CryptoKeyMetadataService manages cryptographic key metadata. | ||
type CryptoKeyMetadataService struct { | ||
CryptoKeyRepo repository.CryptoKeyRepository | ||
} | ||
|
||
// List retrieves all cryptographic key metadata based on a query. | ||
func (s *CryptoKeyMetadataService) List(query *keys.CryptoKeyQuery) ([]*keys.CryptoKeyMeta, error) { | ||
// For now, let's just retrieve all metadata from the database | ||
var keyMetas []*keys.CryptoKeyMeta | ||
// TBD | ||
|
||
return keyMetas, nil | ||
} | ||
|
||
// GetByID retrieves the metadata of a cryptographic key by its ID. | ||
func (s *CryptoKeyMetadataService) GetByID(keyID string) (*keys.CryptoKeyMeta, error) { | ||
// Retrieve the metadata from the database | ||
keyMeta, err := s.CryptoKeyRepo.GetByID(keyID) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to retrieve key metadata: %w", err) | ||
} | ||
|
||
return keyMeta, nil | ||
} | ||
|
||
// DeleteByID deletes a cryptographic key's metadata by its ID. | ||
func (s *CryptoKeyMetadataService) DeleteByID(keyID string) error { | ||
// Delete the metadata from the database | ||
err := s.CryptoKeyRepo.DeleteByID(keyID) | ||
if err != nil { | ||
return fmt.Errorf("failed to delete key metadata: %w", err) | ||
} | ||
return nil | ||
} | ||
|
||
// CryptoKeyDownloadService handles the download of cryptographic keys. | ||
type CryptoKeyDownloadService struct { | ||
VaultConnector connector.VaultConnector | ||
} | ||
|
||
// Download retrieves a cryptographic key by its ID and type. | ||
func (s *CryptoKeyDownloadService) Download(keyID string, keyType keys.KeyType) ([]byte, error) { | ||
blobName := "" // Declare the variable outside the blocks | ||
|
||
if keyType == keys.AsymmetricPublic { | ||
blobName = "asymmetric-public-key" // Assign to the already declared variable | ||
} else if keyType == keys.AsymmetricPrivate { | ||
blobName = "asymmetric-private-key" // Assign to the already declared variable | ||
} else if keyType == keys.Symmetric { | ||
blobName = "symmetric-key" // Assign to the already declared variable | ||
} else { | ||
return nil, fmt.Errorf("unsupported key type: %v", keyType) | ||
} | ||
|
||
blobData, err := s.VaultConnector.Download(keyID, blobName) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to download key from blob storage: %w", err) | ||
} | ||
|
||
// Return the metadata and the downloaded content (as a byte slice) | ||
return blobData, nil | ||
} |
This file contains 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 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 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
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains 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 was deleted.
Oops, something went wrong.
This file contains 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,153 @@ | ||
package connector | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"crypto_vault_service/internal/domain/keys" | ||
"fmt" | ||
"log" | ||
"os" | ||
"time" | ||
|
||
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob" | ||
"github.com/google/uuid" | ||
) | ||
|
||
// VaultConnector is an interface for interacting with custom key storage. | ||
// The current implementation uses Azure Blob Storage, but this may be replaced | ||
// with Azure Key Vault, AWS KMS, or any other cloud-based key management system in the future. | ||
type VaultConnector interface { | ||
// Upload uploads multiple files to the Vault Storage and returns their metadata. | ||
Upload(filePaths []string, userId string) ([]*keys.CryptoKeyMeta, error) | ||
|
||
// Download retrieves a key's content by its ID and name, and returns the data as a byte slice. | ||
Download(blobId, blobName string) ([]byte, error) | ||
|
||
// Delete deletes a key from Vault Storage by its ID and Name, and returns any error encountered. | ||
Delete(blobId, blobName string) error | ||
} | ||
|
||
// AzureVaultConnector is a struct that implements the VaultConnector interface using Azure Blob Storage. | ||
// This is a temporary implementation and may later be replaced with more specialized external key management systems | ||
// like Azure Key Vault or AWS KMS. | ||
type AzureVaultConnector struct { | ||
Client *azblob.Client | ||
ContainerName string | ||
} | ||
|
||
// NewAzureVaultConnector creates a new instance of AzureVaultConnector, which connects to Azure Blob Storage. | ||
// This method can be updated in the future to support a more sophisticated key management system like Azure Key Vault. | ||
func NewAzureVaultConnector(connectionString string, containerName string) (*AzureVaultConnector, error) { | ||
// Create a new Azure Blob client using the provided connection string | ||
client, err := azblob.NewClientFromConnectionString(connectionString, nil) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to create Azure Blob client: %w", err) | ||
} | ||
|
||
// Ensure the container exists (this could be a simple placeholder, or it could be updated later to use a dedicated container for keys) | ||
_, err = client.CreateContainer(context.Background(), containerName, nil) | ||
if err != nil { | ||
// Log container creation failure, but do not fail if container already exists | ||
log.Printf("Failed to create Azure container: %v\n", err) | ||
} | ||
|
||
return &AzureVaultConnector{ | ||
Client: client, | ||
ContainerName: containerName, | ||
}, nil | ||
} | ||
|
||
// Upload uploads multiple files to Azure Blob Storage and returns their metadata. | ||
// In the future, this may be refactored to integrate with more advanced key storage systems like Azure Key Vault. | ||
func (vc *AzureVaultConnector) Upload(filePaths []string, userId string) ([]*keys.CryptoKeyMeta, error) { | ||
var keyMetas []*keys.CryptoKeyMeta | ||
|
||
// Iterate through all file paths and upload each file | ||
for _, filePath := range filePaths { | ||
// Open the file | ||
file, err := os.Open(filePath) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to open file '%s': %w", filePath, err) | ||
} | ||
defer file.Close() | ||
|
||
// Get file information (name, size, etc.) | ||
fileInfo, err := file.Stat() | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to stat file '%s': %w", filePath, err) | ||
} | ||
|
||
// Read the file content into a buffer | ||
buf := new(bytes.Buffer) | ||
_, err = buf.ReadFrom(file) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to read file '%s': %w", filePath, err) | ||
} | ||
|
||
// Generate a unique ID for the key | ||
keyID := uuid.New().String() | ||
|
||
// Create metadata for the uploaded key | ||
keyMeta := &keys.CryptoKeyMeta{ | ||
ID: keyID, | ||
Type: fileInfo.Name(), // one of asymmetric-public-key, asymmetric-private-key, symmetric-key | ||
DateTimeCreated: time.Now(), | ||
UserID: userId, | ||
} | ||
|
||
// Construct the full blob name (ID and Name) | ||
fullBlobName := fmt.Sprintf("%s/%s", keyID, fileInfo.Name()) | ||
|
||
// Upload the blob (file) to Azure Blob Storage | ||
_, err = vc.Client.UploadBuffer(context.Background(), vc.ContainerName, fullBlobName, buf.Bytes(), nil) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to upload blob '%s' to storage: %w", fullBlobName, err) | ||
} | ||
|
||
// Add the metadata to the list | ||
keyMetas = append(keyMetas, keyMeta) | ||
} | ||
|
||
// Return the metadata of the uploaded keys | ||
return keyMetas, nil | ||
} | ||
|
||
// Download retrieves a key's content by its ID and name, and returns the data as a byte slice. | ||
func (vc *AzureVaultConnector) Download(blobId, blobName string) ([]byte, error) { | ||
// Construct the full blob path by combining blob ID and name | ||
fullBlobName := fmt.Sprintf("%s/%s", blobId, blobName) | ||
|
||
// Download the blob from Azure Blob Storage | ||
ctx := context.Background() | ||
get, err := vc.Client.DownloadStream(ctx, vc.ContainerName, fullBlobName, nil) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to download blob '%s': %w", fullBlobName, err) | ||
} | ||
|
||
// Read the content into a buffer | ||
downloadedData := bytes.Buffer{} | ||
_, err = downloadedData.ReadFrom(get.Body) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to read data from blob '%s': %w", fullBlobName, err) | ||
} | ||
|
||
// Return the downloaded data | ||
return downloadedData.Bytes(), nil | ||
} | ||
|
||
// Delete deletes a key from Azure Blob Storage by its ID and Name. | ||
func (vc *AzureVaultConnector) Delete(blobId, blobName string) error { | ||
// Construct the full blob path by combining blob ID and name | ||
fullBlobName := fmt.Sprintf("%s/%s", blobId, blobName) | ||
|
||
// Delete the blob from Azure Blob Storage | ||
ctx := context.Background() | ||
_, err := vc.Client.DeleteBlob(ctx, vc.ContainerName, fullBlobName, nil) | ||
if err != nil { | ||
return fmt.Errorf("failed to delete blob '%s': %w", fullBlobName, err) | ||
} | ||
|
||
// Log the successful deletion | ||
log.Printf("Deleted blob '%s' from storage.\n", fullBlobName) | ||
return nil | ||
} |
File renamed without changes.
File renamed without changes.
Oops, something went wrong.