Skip to content

Commit

Permalink
ISSUE-158 Encode AWS paths
Browse files Browse the repository at this point in the history
  • Loading branch information
hypnoglow committed Aug 21, 2022
1 parent 71e09e8 commit 65b8d23
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 2 deletions.
79 changes: 79 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,85 @@ your repository users won't have to install this plugin.
To do this, you need your charts to have relative URLs in the index. See
[Relative chart URLs](#relative-chart-urls).

<details>
<summary><b>Example of setting up a public repo using <a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/VirtualHosting.html">Virtual hosting of buckets</a></b></summary>

1. Create S3 bucket named `example-bucket` in EU (Frankfurt) `eu-central-1` region.

2. Go to "Permissions", edit Bucket Policy:

```
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:ListBucket",
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::example-bucket",
"arn:aws:s3:::example-bucket/*"
]
}
]
}
```
3. Initialize repository:
```
$ helm s3 init s3://example-bucket
Initialized empty repository at s3://example-bucket
```
4. Add repository:
```
$ helm repo add example-bucket s3://example-bucket
"example-bucket" has been added to your repositories
```
5. Create demo chart:
```
$ helm create petstore
Creating petstore
$ helm package petstore --version 1.0.0
Successfully packaged chart and saved it to: petstore-1.0.0.tgz
```
6. Push chart:
```
$ helm s3 push ./petstore-1.0.0.tgz --relative
Successfully uploaded the chart to the repository.
```
7. The bucket is public and chart repo is set up. Now users can use the repo
without the need to install helm-s3 plugin.
Add HTTP repo:
```
$ helm repo add example-bucket-http https://example-bucket.s3.eu-central-1.amazonaws.com/
"example-bucket-http" has been added to your repositories
```
Search and download charts:
```
$ helm search repo example-bucket-http
NAME CHART VERSION APP VERSION DESCRIPTION
example-bucket-http/petstore 1.0.0 1.16.0 A Helm chart for Kubernetes
$ helm pull example-bucket-http/petstore --version 1.0.0
```
</details>
### ACLs
In use cases where you share a repo across multiple AWS accounts, you may want
Expand Down
6 changes: 5 additions & 1 deletion cmd/helm-s3/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,11 +199,15 @@ func (act *pushAction) run(ctx context.Context) error {
if err := idx.UnmarshalBinary(b); err != nil {
return errors.WithMessage(err, "load index from downloaded file")
}

baseURL := repoEntry.URL()
if act.relative {
baseURL = ""
}
if err := idx.AddOrReplace(chart.Metadata().Value(), fname, baseURL, hash); err != nil {

filename := escapeIfRelative(fname, act.relative)

if err := idx.AddOrReplace(chart.Metadata().Value(), filename, baseURL, hash); err != nil {
return errors.WithMessage(err, "add/replace chart in the index")
}
idx.SortEntries()
Expand Down
5 changes: 4 additions & 1 deletion cmd/helm-s3/reindex.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,10 @@ func (act *reindexAction) run(ctx context.Context) error {
if act.relative {
baseURL = ""
}
if err := idx.Add(item.Meta.Value(), item.Filename, baseURL, item.Hash); err != nil {

filename := escapeIfRelative(item.Filename, act.relative)

if err := idx.Add(item.Meta.Value(), filename, baseURL, item.Hash); err != nil {
act.printer.PrintErrf("[ERROR] failed to add chart to the index: %s", err)
}
}
Expand Down
21 changes: 21 additions & 0 deletions cmd/helm-s3/util.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,27 @@
package main

import "github.com/hypnoglow/helm-s3/internal/awsutil"

type printer interface {
Printf(format string, v ...interface{})
PrintErrf(format string, i ...interface{})
}

// escapeIfRelative escapes chart filename if it is indexed as relative.
//
// Note: we escape filename only if 'relative' is set for a few reasons:
// - Full URLs don't need to be escaped because with full URLs in the index
// the charts can be downloaded only with this plugin;
// - Even if we escape the filename here, the code in Index.Add and
// Index.AddOrReplace (in particular, the call to urlutil.URLJoin) will
// break the URL, e.g. the escaped filename "petstore-1.0.0%2B102.tgz"
// with the "s3://example-bucket" baseURL will become
// "s3://example-bucket/petstore-1.0.0%252B102.tgz".
// So if we ever decide to escape, we need to fix this.
func escapeIfRelative(filename string, relative bool) string {
if !relative {
return filename
}

return awsutil.EscapePath(filename)
}
10 changes: 10 additions & 0 deletions internal/awsutil/url.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package awsutil

import "github.com/aws/aws-sdk-go/private/protocol/rest"

// EscapePath escapes URL path according to AWS escaping rules.
//
// This func can be used to escape S3 object keys for HTTP access.
func EscapePath(path string) string {
return rest.EscapePath(path, true)
}

0 comments on commit 65b8d23

Please sign in to comment.