Skip to content

Commit 2bfd640

Browse files
committed
azure: Create SAS for blobs
Creating SAS url for ignition blobs using user delegated credentials.
1 parent 0dff456 commit 2bfd640

2 files changed

Lines changed: 49 additions & 27 deletions

File tree

pkg/infrastructure/azure/azure.go

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import (
1717
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4"
1818
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2"
1919
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage"
20+
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/sas"
21+
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/service"
2022
"github.com/coreos/stream-metadata-go/arch"
2123
"github.com/sirupsen/logrus"
2224
corev1 "k8s.io/api/core/v1"
@@ -275,7 +277,7 @@ func (p *Provider) InfraReady(ctx context.Context, in clusterapi.InfraReadyInput
275277
blobContainer := createBlobContainerOutput.BlobContainer
276278
logrus.Debugf("BlobContainer.ID=%s", *blobContainer.ID)
277279

278-
_, err = CreatePageBlob(ctx, &CreatePageBlobInput{
280+
err = CreatePageBlob(ctx, &CreatePageBlobInput{
279281
StorageURL: storageURL,
280282
BlobURL: blobURL,
281283
ImageURL: imageURL,
@@ -740,8 +742,25 @@ func (p Provider) Ignition(ctx context.Context, in clusterapi.IgnitionInput) ([]
740742
blobIgnitionContainer = createBlobContainerOutput.BlobContainer
741743
logrus.Debugf("BlobIgnitionContainer.ID=%s", *blobIgnitionContainer.ID)
742744
}
743-
744745
sasURL := ""
746+
now := time.Now().UTC().Add(-10 * time.Second)
747+
expiry := now.Add(1 * time.Hour)
748+
info := service.KeyInfo{
749+
Start: to.Ptr(now.UTC().Format(sas.TimeFormat)),
750+
Expiry: to.Ptr(expiry.UTC().Format(sas.TimeFormat)),
751+
}
752+
753+
serviceClient, err := service.NewClient(fmt.Sprintf("https://%s.blob.core.windows.net/", p.StorageAccountName),
754+
session.TokenCreds,
755+
&service.ClientOptions{},
756+
)
757+
if err != nil {
758+
return nil, fmt.Errorf("failed to create service client: %w", err)
759+
}
760+
udc, err := serviceClient.GetUserDelegationCredential(context.Background(), info, nil)
761+
if err != nil {
762+
return nil, fmt.Errorf("failed to create user delegation credentials: %w", err)
763+
}
745764

746765
if in.InstallConfig.Config.Azure.CustomerManagedKey == nil {
747766
logrus.Debugf("Creating a Block Blob for ignition shim")
@@ -774,7 +793,7 @@ func (p Provider) Ignition(ctx context.Context, in clusterapi.IgnitionInput) ([]
774793
lengthBootstrapFile = (((lengthBootstrapFile / 512) + 1) * 512)
775794
}
776795

777-
sasURL, err = CreatePageBlob(ctx, &CreatePageBlobInput{
796+
err = CreatePageBlob(ctx, &CreatePageBlobInput{
778797
StorageURL: p.StorageURL,
779798
BlobURL: blobURL,
780799
ImageURL: "",
@@ -790,6 +809,22 @@ func (p Provider) Ignition(ctx context.Context, in clusterapi.IgnitionInput) ([]
790809
return nil, fmt.Errorf("failed to create PageBlob for ignition shim: %w", err)
791810
}
792811
}
812+
813+
// Should we separate azurestack from azure when using the user delegated SAS?
814+
// Azurestack is generating an SAS url at this point.
815+
if sasURL != "" {
816+
sasQueryParams, err := sas.BlobSignatureValues{
817+
Protocol: sas.ProtocolHTTPS,
818+
StartTime: time.Now().UTC().Add(time.Second * -10),
819+
ExpiryTime: time.Now().UTC().Add(1 * time.Hour),
820+
Permissions: to.Ptr(sas.ContainerPermissions{Read: true, List: true, Write: true, Create: true}).String(),
821+
BlobName: blobName,
822+
}.SignWithUserDelegation(udc)
823+
if err != nil {
824+
return nil, fmt.Errorf("failed to sign blob %s: %w", blobURL, err)
825+
}
826+
sasURL = fmt.Sprintf("https://%s.blob.core.windows.net/ignition/%s?%s", p.StorageAccountName, blobName, sasQueryParams.Encode())
827+
}
793828
ignShim, err := bootstrap.GenerateIgnitionShimWithCertBundleAndProxy(sasURL, in.InstallConfig.Config.AdditionalTrustBundle, in.InstallConfig.Config.Proxy)
794829
if err != nil {
795830
return nil, fmt.Errorf("failed to create ignition shim: %w", err)

pkg/infrastructure/azure/storage.go

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ type CreatePageBlobInput struct {
231231
ImageURL string
232232
StorageAccountName string
233233
BootstrapIgnData []byte
234+
UserDelegatedSAS *sas.UserDelegationCredential
234235
ImageLength int64
235236
AuthType azic.AuthenticationType
236237
TokenCredential azcore.TokenCredential
@@ -245,7 +246,7 @@ type CreatePageBlobOutput struct {
245246
}
246247

247248
// CreatePageBlob creates a blob and uploads a file from a URL to it.
248-
func CreatePageBlob(ctx context.Context, in *CreatePageBlobInput) (string, error) {
249+
func CreatePageBlob(ctx context.Context, in *CreatePageBlobInput) error {
249250
logrus.Debugf("Getting page blob client")
250251

251252
pageBlobClient, err := pageblob.NewClient(
@@ -258,19 +259,19 @@ func CreatePageBlob(ctx context.Context, in *CreatePageBlobInput) (string, error
258259
},
259260
)
260261
if err != nil {
261-
return "", fmt.Errorf("failed to get page blob client: %w", err)
262+
return fmt.Errorf("failed to get page blob client: %w", err)
262263
}
263264

264265
logrus.Debugf("Creating Page blob and uploading image to it")
265266
if in.ImageURL == "" {
266267
_, err = pageBlobClient.Create(ctx, in.ImageLength, nil)
267268
if err != nil {
268-
return "", fmt.Errorf("failed to create page blob with image contents: %w", err)
269+
return fmt.Errorf("failed to create page blob with image contents: %w", err)
269270
}
270271
// This image (example: ignition shim) needs to be uploaded from a local file.
271272
err = doUploadPages(ctx, pageBlobClient, in.BootstrapIgnData, in.ImageLength)
272273
if err != nil {
273-
return "", fmt.Errorf("failed to upload page blob image contents: %w", err)
274+
return fmt.Errorf("failed to upload page blob image contents: %w", err)
274275
}
275276
} else {
276277
// This is used in terraform, not sure if it matters
@@ -282,26 +283,15 @@ func CreatePageBlob(ctx context.Context, in *CreatePageBlobInput) (string, error
282283
Metadata: metadata,
283284
})
284285
if err != nil {
285-
return "", fmt.Errorf("failed to create page blob with image URL: %w", err)
286+
return fmt.Errorf("failed to create page blob with image URL: %w", err)
286287
}
287288

288289
err = doUploadPagesFromURL(ctx, pageBlobClient, in.ImageURL, in.ImageLength)
289290
if err != nil {
290-
return "", fmt.Errorf("failed to upload page blob image from URL %s: %w", in.ImageURL, err)
291+
return fmt.Errorf("failed to upload page blob image from URL %s: %w", in.ImageURL, err)
291292
}
292293
}
293-
294-
// SAS not supported when using managed identity.
295-
if in.AuthType == azic.ManagedIdentityAuth {
296-
return pageBlobClient.URL(), nil
297-
}
298-
299-
// Is this addition OK for when CreatePageBlob() is called from InfraReady()
300-
sasURL, err := pageBlobClient.GetSASURL(sas.BlobPermissions{Read: true}, time.Now().Add(time.Minute*60), &blob.GetSASURLOptions{})
301-
if err != nil {
302-
return "", fmt.Errorf("failed to get Page Blob SAS URL: %w", err)
303-
}
304-
return sasURL, nil
294+
return nil
305295
}
306296

307297
func doUploadPages(ctx context.Context, pageBlobClient *pageblob.Client, imageData []byte, imageLength int64) error {
@@ -454,6 +444,7 @@ type CreateBlockBlobInput struct {
454444
CloudEnvironment aztypes.CloudEnvironment
455445
ContainerName string
456446
BlobName string
447+
UserDelegatedSAS *sas.UserDelegationCredential
457448
StorageSuffix string
458449
ARMEndpoint string
459450
Region string
@@ -512,12 +503,7 @@ func createBlockBlob(ctx context.Context, in *CreateBlockBlobInput, sharedKeyCre
512503
if in.AuthType == azic.ManagedIdentityAuth {
513504
return blockBlobClient.URL(), nil
514505
}
515-
516-
sasURL, err := blockBlobClient.GetSASURL(sas.BlobPermissions{Read: true}, time.Now().Add(time.Minute*60), &blob.GetSASURLOptions{})
517-
if err != nil {
518-
return "", fmt.Errorf("failed to get SAS URL: %w", err)
519-
}
520-
return sasURL, nil
506+
return "", nil
521507
}
522508

523509
func createBlockBlobOnStack(ctx context.Context, in *CreateBlockBlobInput) (string, error) {
@@ -598,6 +584,7 @@ func uploadBlockBlobOnStack(in *CreateBlockBlobInput, key string) (string, error
598584
}
599585
return sas, nil
600586
}
587+
601588
// CustomerManagedKeyInput contains the input parameters for creating the
602589
// customer managed key and identity.
603590
type CustomerManagedKeyInput struct {

0 commit comments

Comments
 (0)