obs-access-signer/obs_storj.go

179 lines
4.9 KiB
Go

package main
import (
"context"
"flag"
"os"
"github.com/pkg/errors"
"storj.io/uplink"
"storj.io/uplink/edge"
)
type obsStorjOptions struct {
SatelliteAddress string
APIKey string
Passphrase string
AccessGrant string
AccessKeyID string
ShareBaseURL string
}
var defaultObsUplinkOpts = obsStorjOptions{
// we can override satellite address from Access Grant with this
// ex. "ap1.storj.io:7777"
SatelliteAddress: "",
ShareBaseURL: "https://link.storjshare.io",
}
func (opts *obsStorjOptions) Bind(fs *flag.FlagSet) (err error) {
var vSatelliteAddr = opts.SatelliteAddress
if sSatelliteAddr := os.Getenv("UPLINK_SATELLITE_ADDR"); sSatelliteAddr != "" {
vSatelliteAddr = sSatelliteAddr
}
fs.StringVar(&opts.SatelliteAddress, "uplink-satellite-addr", vSatelliteAddr, "OBS Storj Satellite Address")
{
var vAPIKey = opts.APIKey
if sAPIKey := os.Getenv("UPLINK_API_KEY"); sAPIKey != "" {
vAPIKey = sAPIKey
}
fs.StringVar(&opts.APIKey, "uplink-api-key", vAPIKey, "OBS Storj API key")
var vPassphrase = opts.Passphrase
if sPassphrase := os.Getenv("UPLINK_PASSPHRASE"); sPassphrase != "" {
vPassphrase = sPassphrase
}
fs.StringVar(&opts.Passphrase, "uplink-passphrase", vPassphrase, "OBS Storj Passphrase")
}
var vAccessGrant = opts.AccessGrant
if sAccessGrant := os.Getenv("UPLINK_ACCESS_GRANT"); sAccessGrant != "" {
vAccessGrant = sAccessGrant
}
fs.StringVar(&opts.AccessGrant, "uplink-access-grant", vAccessGrant, "OBS Storj Access Grant")
var vAccessKeyID = opts.AccessKeyID
if sAccessKeyID := os.Getenv("UPLINK_ACCESS_KEY_ID"); sAccessKeyID != "" {
vAccessKeyID = sAccessKeyID
}
fs.StringVar(&opts.AccessKeyID, "uplink-access-key-id", vAccessKeyID, "OBS Storj Access key ID")
var vShareBaseURL = opts.ShareBaseURL
if sShareBaseURL := os.Getenv("UPLINK_SHARE_BASE_URL"); sShareBaseURL != "" {
vShareBaseURL = sShareBaseURL
}
fs.StringVar(&opts.ShareBaseURL, "uplink-share-base-url", vShareBaseURL, "OBS Storj Link Share base URL")
return
}
var defaultEdgeConfig = edge.Config{
AuthServiceAddress: "auth.storjshare.io:7777",
}
type storjAggegrateClient struct {
edgeConfig *edge.Config
access *uplink.Access
project *uplink.Project
creds *edge.Credentials
accessKeyID string
shareBaseURL string
}
func (c *storjAggegrateClient) Init(ctx context.Context) (_ *storjAggegrateClient, err error) {
if c.access != nil {
// TODO: rate limit this, persist the registered access key ID
if c.creds, err = c.edgeConfig.RegisterAccess(ctx, c.access, &edge.RegisterAccessOptions{
// This will create `accessKeyID` that allow anonymous access
// to any objects that `c.access` has access to (just like `public-read` ACL).
Public: true,
}); err != nil {
err = errors.Wrap(err, "register access")
return
}
}
return c, nil
}
func (c *storjAggegrateClient) getAccessKeyID() (accessKeyID string) {
accessKeyID = c.accessKeyID
// fallback to `c.creds` if custom accessKeyID is not provided
// and `c.creds` is specified.
if accessKeyID == "" && c.creds != nil {
accessKeyID = c.creds.AccessKeyID
}
return
}
func (c *storjAggegrateClient) getProject() *uplink.Project {
return c.project
}
func (c *storjAggegrateClient) JoinShareURL(bucket, key string, opts *edge.ShareURLOptions) (string, error) {
accessKeyID := c.getAccessKeyID()
return edge.JoinShareURL(c.shareBaseURL, accessKeyID, bucket, key, opts)
}
func newObsStorjClient(ctx context.Context, opts obsStorjOptions) (client *storjAggegrateClient, err error) {
var (
access *uplink.Access
project *uplink.Project
)
switch {
case opts.AccessGrant != "":
// Docs: https://docs.storj.io/dcs/concepts/access/access-grants
access, err = uplink.ParseAccess(opts.AccessGrant)
if err != nil {
err = errors.Wrap(err, "parse access")
return
}
case opts.APIKey != "" && opts.Passphrase != "":
// Docs: https://docs.storj.io/dcs/getting-started/quickstart-uplink-cli/generate-access-grants-and-tokens/generate-a-token
if access, err = uplink.RequestAccessWithPassphrase(
ctx,
opts.SatelliteAddress,
opts.APIKey,
opts.Passphrase,
); err != nil {
err = errors.Wrap(err, "access with passphrase")
return
}
default:
// using custom accessKeyID
access = nil
}
// TODO: limit access scope.
if access != nil {
// Consider to limit the access to specific bucket and prefix
// access, err = access.Share(
// uplink.ReadOnlyPermission(),
// uplink.SharePrefix{
// Bucket: "",
// Prefix: "",
// })
// open project
project, err = uplink.OpenProject(ctx, access)
if err != nil {
err = errors.Wrap(err, "open project")
return
}
}
// fallback default link sharing base url
if opts.ShareBaseURL == "" {
opts.ShareBaseURL = defaultObsUplinkOpts.ShareBaseURL
}
return (&storjAggegrateClient{
edgeConfig: &defaultEdgeConfig,
access: access,
project: project,
accessKeyID: opts.AccessKeyID,
shareBaseURL: opts.ShareBaseURL,
}).Init(ctx)
}