Skip to content

Commit

Permalink
Fix/s3 cache (#121)
Browse files Browse the repository at this point in the history
* fix: Due read after write consistency in S3 missingLayers called the actual object that created cache 403 response
This change creating index file for each object so missingLayers will not hit object that not exist.

* fix comments error description

Co-authored-by: oranmoshai <[email protected]>
  • Loading branch information
oranmoshai and oranmoshai authored Jun 10, 2020
1 parent c527757 commit 2c761b0
Showing 1 changed file with 26 additions and 15 deletions.
41 changes: 26 additions & 15 deletions cache/s3.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,13 @@ import (
"bytes"
"encoding/json"
"fmt"

"github.com/aquasecurity/fanal/types"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/aws/aws-sdk-go/service/s3/s3iface"
"github.com/aws/aws-sdk-go/service/s3/s3manager/s3manageriface"
"github.com/google/go-containerregistry/pkg/v1"
"golang.org/x/xerrors"

"github.com/aquasecurity/fanal/types"
)

var _ Cache = &S3Cache{}
Expand Down Expand Up @@ -66,12 +64,13 @@ func (c S3Cache) put(key string, body interface{}) (err error) {
if err != nil {
return xerrors.Errorf("unable to put object: %w", err)
}
headObjectInput := &s3.HeadObjectInput{
//Index file due S3 caveat read after write consistency
_, err = c.s3Client.PutObject(&s3.PutObjectInput{
Bucket: aws.String(c.bucketName),
Key: aws.String(key),
}
if err = c.s3Client.WaitUntilObjectExists(headObjectInput); err != nil {
return xerrors.Errorf("information was not found in cache: %w", err)
Key: aws.String(fmt.Sprintf("%s.index", key)),
})
if err != nil {
return xerrors.Errorf("unable to put index object: %w", err)
}
return nil
}
Expand All @@ -90,13 +89,11 @@ func (c S3Cache) GetBlob(blobID string) (types.BlobInfo, error) {
if err != nil {
return types.BlobInfo{}, xerrors.Errorf("JSON unmarshal error: %w", err)
}

return blobInfo, nil
}

func (c S3Cache) GetArtifact(artifactID string) (types.ArtifactInfo, error) {
var info types.ArtifactInfo

buf := aws.NewWriteAtBuffer([]byte{})
_, err := c.downloader.Download(buf, &s3.GetObjectInput{
Bucket: aws.String(c.bucketName),
Expand All @@ -109,34 +106,48 @@ func (c S3Cache) GetArtifact(artifactID string) (types.ArtifactInfo, error) {
if err != nil {
return types.ArtifactInfo{}, xerrors.Errorf("JSON unmarshal error: %w", err)
}

return info, nil
}

func (c S3Cache) getIndex(key string, keyType string) error {
_, err := c.s3Client.HeadObject(&s3.HeadObjectInput{Key: aws.String(fmt.Sprintf("%s/%s/%s.index", keyType, c.prefix, key))})
if err != nil {
return xerrors.Errorf("failed to get index from the cache: %w", err)
}
return nil
}

func (c S3Cache) MissingBlobs(artifactID string, blobIDs []string) (bool, []string, error) {
var missingArtifact bool
var missingBlobIDs []string
for _, blobID := range blobIDs {
blobInfo, err := c.GetBlob(blobID)
err := c.getIndex(blobID, blobBucket)
if err != nil {
// error means cache missed blob info
missingBlobIDs = append(missingBlobIDs, blobID)
continue
}
blobInfo, err := c.GetBlob(blobID)
if err != nil {
return true, missingBlobIDs, xerrors.Errorf("the blob object (%s) doesn't exist in S3 even though the index file exists: %w", blobID, err)
}
if blobInfo.SchemaVersion != types.BlobJSONSchemaVersion {
missingBlobIDs = append(missingBlobIDs, blobID)
}
}
// get artifact info
artifactInfo, err := c.GetArtifact(artifactID)
err := c.getIndex(artifactID, artifactBucket)
// error means cache missed artifact info
if err != nil {
// error means cache missed artifact info
return true, missingBlobIDs, nil
}
artifactInfo, err := c.GetArtifact(artifactID)
if err != nil {
return true, missingBlobIDs, xerrors.Errorf("the artifact object (%s) doesn't exist in S3 even though the index file exists: %w", artifactID, err)
}
if artifactInfo.SchemaVersion != types.ArtifactJSONSchemaVersion {
missingArtifact = true
}

return missingArtifact, missingBlobIDs, nil
}

Expand Down

0 comments on commit 2c761b0

Please sign in to comment.