diff --git a/internal/providers/akamai/akamai.go b/internal/providers/akamai/akamai.go index 648be3bee..0f9697087 100644 --- a/internal/providers/akamai/akamai.go +++ b/internal/providers/akamai/akamai.go @@ -86,12 +86,18 @@ func fetchConfig(f *resource.Fetcher) (types.Config, report.Report, error) { // The Linode Metadata Service requires userdata to be base64-encoded // when it is uploaded, so we will have to decode the response. data := make([]byte, base64.StdEncoding.DecodedLen(len(encoded))) - n, err := base64.StdEncoding.Decode(data, encoded) - if err != nil { + if _, err := base64.StdEncoding.Decode(data, encoded); err != nil { return types.Config{}, report.Report{}, fmt.Errorf("decode base64: %w", err) } - return util.ParseConfig(f.Logger, data[:n]) + // The Linode Metadata Service can compress userdata. + // We have to gunzip if needed. + unzipData, err := util.GunzipIfNeeded(data) + if err != nil { + return types.Config{}, report.Report{}, fmt.Errorf("unzip: %w", err) + } + + return util.ParseConfig(f.Logger, unzipData) } // defaultTokenTTL is the time-to-live (TTL; in seconds) for an authorization diff --git a/internal/providers/util/unzip.go b/internal/providers/util/unzip.go new file mode 100644 index 000000000..29858c655 --- /dev/null +++ b/internal/providers/util/unzip.go @@ -0,0 +1,27 @@ +package util + +import ( + "bytes" + "compress/gzip" + "io" +) + +var ( + gzipMagic = []byte{0x1F, 0x8B, 0x08} +) + +func hasGzipMagicNumber(source []byte) bool { + return bytes.HasPrefix(source, gzipMagic) +} + +func GunzipIfNeeded(raw []byte) ([]byte, error) { + if hasGzipMagicNumber(raw) { + reader, err := gzip.NewReader(bytes.NewReader(raw)) + if err != nil { + return nil, err + } + defer reader.Close() + return io.ReadAll(reader) + } + return raw, nil +}