You've already forked golang-saas-starter-kit
mirror of
https://github.com/raseels-repos/golang-saas-starter-kit.git
synced 2025-07-03 00:58:13 +02:00
completed autocert implimentation for web-api
This commit is contained in:
@ -2,9 +2,10 @@ package mid
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"geeks-accelerator/oss/saas-starter-kit/example-project/internal/platform/web"
|
||||
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type (
|
||||
@ -25,7 +26,7 @@ type (
|
||||
// DomainNameRedirectConfig defines the details needed to apply redirects based on domain names.
|
||||
DomainNameRedirectConfig struct {
|
||||
RedirectConfig
|
||||
DomainName string
|
||||
DomainName string
|
||||
HTTPSEnabled bool
|
||||
}
|
||||
|
||||
@ -50,14 +51,12 @@ func DefaultSkipper(ctx context.Context, w http.ResponseWriter, r *http.Request,
|
||||
|
||||
// HTTPSRedirectWithConfig returns an HTTPSRedirect middleware with config.
|
||||
// See `HTTPSRedirect()`.
|
||||
func DomainNameRedirect(config DomainNameRedirectConfig) web.Middleware {
|
||||
func DomainNameRedirect(config DomainNameRedirectConfig) web.Middleware {
|
||||
return redirect(config.RedirectConfig, func(scheme, host, uri string) (ok bool, url string) {
|
||||
|
||||
// Redirects http requests to https.
|
||||
if config.HTTPSEnabled {
|
||||
if ok = scheme != "https"; ok {
|
||||
url = "https://" + host + uri
|
||||
|
||||
scheme = "https"
|
||||
}
|
||||
}
|
||||
@ -65,16 +64,15 @@ func DomainNameRedirect(config DomainNameRedirectConfig) web.Middleware {
|
||||
// Redirects all domain name alternatives to the primary hostname.
|
||||
if host != config.DomainName {
|
||||
host = config.DomainName
|
||||
ok = true
|
||||
}
|
||||
|
||||
|
||||
url = scheme + "://" + host + uri
|
||||
|
||||
return
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// HTTPSRedirect redirects http requests to https.
|
||||
// For example, http://geeksinthewoods.com will be redirect to https://geeksinthewoods.com.
|
||||
func HTTPSRedirect() web.Middleware {
|
||||
@ -83,7 +81,7 @@ func HTTPSRedirect() web.Middleware {
|
||||
|
||||
// HTTPSRedirectWithConfig returns an HTTPSRedirect middleware with config.
|
||||
// See `HTTPSRedirect()`.
|
||||
func HTTPSRedirectWithConfig(config RedirectConfig)web.Middleware {
|
||||
func HTTPSRedirectWithConfig(config RedirectConfig) web.Middleware {
|
||||
return redirect(config, func(scheme, host, uri string) (ok bool, url string) {
|
||||
if ok = scheme != "https"; ok {
|
||||
url = "https://" + host + uri
|
||||
@ -100,7 +98,7 @@ func HTTPSWWWRedirect() web.Middleware {
|
||||
|
||||
// HTTPSWWWRedirectWithConfig returns an HTTPSRedirect middleware with config.
|
||||
// See `HTTPSWWWRedirect()`.
|
||||
func HTTPSWWWRedirectWithConfig(config RedirectConfig) web.Middleware {
|
||||
func HTTPSWWWRedirectWithConfig(config RedirectConfig) web.Middleware {
|
||||
return redirect(config, func(scheme, host, uri string) (ok bool, url string) {
|
||||
if ok = scheme != "https" && host[:3] != www; ok {
|
||||
url = "https://www." + host + uri
|
||||
@ -117,7 +115,7 @@ func HTTPSNonWWWRedirect() web.Middleware {
|
||||
|
||||
// HTTPSNonWWWRedirectWithConfig returns an HTTPSRedirect middleware with config.
|
||||
// See `HTTPSNonWWWRedirect()`.
|
||||
func HTTPSNonWWWRedirectWithConfig(config RedirectConfig) web.Middleware {
|
||||
func HTTPSNonWWWRedirectWithConfig(config RedirectConfig) web.Middleware {
|
||||
return redirect(config, func(scheme, host, uri string) (ok bool, url string) {
|
||||
if ok = scheme != "https"; ok {
|
||||
if host[:3] == www {
|
||||
@ -154,7 +152,7 @@ func NonWWWRedirect() web.Middleware {
|
||||
|
||||
// NonWWWRedirectWithConfig returns an HTTPSRedirect middleware with config.
|
||||
// See `NonWWWRedirect()`.
|
||||
func NonWWWRedirectWithConfig(config RedirectConfig) web.Middleware {
|
||||
func NonWWWRedirectWithConfig(config RedirectConfig) web.Middleware {
|
||||
return redirect(config, func(scheme, host, uri string) (ok bool, url string) {
|
||||
if ok = host[:3] == www; ok {
|
||||
url = scheme + "://" + host[4:] + uri
|
||||
|
@ -7,26 +7,28 @@ import (
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/aws/aws-sdk-go/service/secretsmanager"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/crypto/acme/autocert"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
)
|
||||
|
||||
// SecretManagerAutocertCache implements the autocert.Cache interface for AWS Secrets Manager that is used by Manager
|
||||
// to store and retrieve previously obtained certificates and other account data as opaque blobs.
|
||||
type SecretManagerAutocertCache struct {
|
||||
awsSession *session.Session
|
||||
log *log.Logger
|
||||
type SecretManagerAutocertCache struct {
|
||||
awsSession *session.Session
|
||||
log *log.Logger
|
||||
secretPrefix string
|
||||
cache autocert.Cache
|
||||
}
|
||||
|
||||
// NewSecretManagerAutocertCache provides the functionality to keep config files sync'd between running tasks and across deployments.
|
||||
func NewSecretManagerAutocertCache(log *log.Logger, awsSession *session.Session, secretPrefix string ) (*SecretManagerAutocertCache, error) {
|
||||
func NewSecretManagerAutocertCache(log *log.Logger, awsSession *session.Session, secretPrefix string, cache autocert.Cache) (*SecretManagerAutocertCache, error) {
|
||||
return &SecretManagerAutocertCache{
|
||||
awsSession,
|
||||
log,
|
||||
secretPrefix,
|
||||
cache,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -34,6 +36,16 @@ func NewSecretManagerAutocertCache(log *log.Logger, awsSession *session.Session,
|
||||
// If there's no such key, Get returns ErrCacheMiss.
|
||||
func (c *SecretManagerAutocertCache) Get(ctx context.Context, key string) ([]byte, error) {
|
||||
|
||||
// Check short term cache.
|
||||
if c.cache != nil {
|
||||
v, err := c.cache.Get(ctx, key)
|
||||
if err != nil && err != autocert.ErrCacheMiss {
|
||||
return nil, errors.WithStack(err)
|
||||
} else if len(v) > 0 {
|
||||
return v, nil
|
||||
}
|
||||
}
|
||||
|
||||
svc := secretsmanager.New(c.awsSession)
|
||||
|
||||
secretID := filepath.Join(c.secretPrefix, key)
|
||||
@ -43,7 +55,7 @@ func (c *SecretManagerAutocertCache) Get(ctx context.Context, key string) ([]byt
|
||||
SecretId: aws.String(secretID),
|
||||
})
|
||||
if err != nil {
|
||||
if aerr, ok := err.(awserr.Error); ok && aerr.Code() == secretsmanager.ErrCodeResourceNotFoundException {
|
||||
if aerr, ok := err.(awserr.Error); ok && (aerr.Code() == secretsmanager.ErrCodeResourceNotFoundException || aerr.Code() == secretsmanager.ErrCodeInvalidRequestException) {
|
||||
return nil, autocert.ErrCacheMiss
|
||||
}
|
||||
|
||||
@ -52,7 +64,7 @@ func (c *SecretManagerAutocertCache) Get(ctx context.Context, key string) ([]byt
|
||||
|
||||
log.Printf("AWS Secrets Manager : Secret %s found", secretID)
|
||||
|
||||
return res.SecretBinary, nil
|
||||
return []byte(*res.SecretString), nil
|
||||
}
|
||||
|
||||
// Put stores the data in the cache under the specified key.
|
||||
@ -70,28 +82,27 @@ func (c *SecretManagerAutocertCache) Put(ctx context.Context, key string, data [
|
||||
SecretString: aws.String(string(data)),
|
||||
})
|
||||
if err != nil {
|
||||
if aerr, ok := err.(awserr.Error); !ok {
|
||||
aerr, ok := err.(awserr.Error)
|
||||
|
||||
if aerr.Code() == secretsmanager.ErrCodeInvalidRequestException {
|
||||
// InvalidRequestException: You can't create this secret because a secret with this
|
||||
// name is already scheduled for deletion.
|
||||
if ok && aerr.Code() == secretsmanager.ErrCodeInvalidRequestException {
|
||||
// InvalidRequestException: You can't create this secret because a secret with this
|
||||
// name is already scheduled for deletion.
|
||||
|
||||
// Restore secret after it was already previously deleted.
|
||||
_, err = svc.RestoreSecret(&secretsmanager.RestoreSecretInput{
|
||||
SecretId: aws.String(secretID),
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "autocert failed to restore secret %s", secretID)
|
||||
}
|
||||
|
||||
} else if aerr.Code() != secretsmanager.ErrCodeResourceExistsException {
|
||||
return errors.Wrapf(err, "autocert failed to create secret %s", secretID)
|
||||
// Restore secret after it was already previously deleted.
|
||||
_, err = svc.RestoreSecret(&secretsmanager.RestoreSecretInput{
|
||||
SecretId: aws.String(secretID),
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "autocert failed to restore secret %s", secretID)
|
||||
}
|
||||
|
||||
} else if !ok || aerr.Code() != secretsmanager.ErrCodeResourceExistsException {
|
||||
return errors.Wrapf(err, "autocert failed to create secret %s", secretID)
|
||||
}
|
||||
|
||||
// If where was a resource exists error for create, then need to update the secret instead.
|
||||
_, err = svc.UpdateSecret(&secretsmanager.UpdateSecretInput{
|
||||
SecretId: aws.String(secretID),
|
||||
SecretId: aws.String(secretID),
|
||||
SecretString: aws.String(string(data)),
|
||||
})
|
||||
if err != nil {
|
||||
@ -103,6 +114,13 @@ func (c *SecretManagerAutocertCache) Put(ctx context.Context, key string, data [
|
||||
log.Printf("AWS Secrets Manager : Secret %s created", secretID)
|
||||
}
|
||||
|
||||
if c.cache != nil {
|
||||
err = c.cache.Put(ctx, key, data)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -116,7 +134,7 @@ func (c *SecretManagerAutocertCache) Delete(ctx context.Context, key string) err
|
||||
|
||||
// Create the new entry in AWS Secret Manager for the file.
|
||||
_, err := svc.DeleteSecret(&secretsmanager.DeleteSecretInput{
|
||||
SecretId: aws.String(secretID),
|
||||
SecretId: aws.String(secretID),
|
||||
|
||||
// (Optional) Specifies that the secret is to be deleted without any recovery
|
||||
// window. You can't use both this parameter and the RecoveryWindowInDays parameter
|
||||
@ -145,7 +163,14 @@ func (c *SecretManagerAutocertCache) Delete(ctx context.Context, key string) err
|
||||
return errors.Wrapf(err, "autocert failed to delete secret %s", secretID)
|
||||
}
|
||||
|
||||
log.Printf("AWS Secrets Manager : Secret %s deleted for %s", secretID)
|
||||
log.Printf("AWS Secrets Manager : Secret %s deleted", secretID)
|
||||
|
||||
if c.cache != nil {
|
||||
err = c.cache.Delete(ctx, key)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ func SyncCfgInit(log *log.Logger, awsSession *session.Session, secretPrefix, wat
|
||||
localfiles := make(map[string]time.Time)
|
||||
|
||||
// Do the initial sync before starting file watch to download any existing configs.
|
||||
err := SyncCfgDir(log, awsSession, secretPrefix, watchDir, localfiles)
|
||||
err := SyncCfgDir(log, awsSession, secretPrefix, watchDir, localfiles)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -41,7 +41,6 @@ func SyncCfgInit(log *log.Logger, awsSession *session.Session, secretPrefix, wat
|
||||
// Init the watch to wait for sync local files to Secret Manager.
|
||||
WatchCfgDir(log, awsSession, secretPrefix, watchDir, watcher, localfiles)
|
||||
|
||||
|
||||
// Init ticker to sync remote files from Secret Manager locally at the defined interval.
|
||||
if syncInterval.Seconds() > 0 {
|
||||
ticker := time.NewTicker(syncInterval)
|
||||
@ -52,7 +51,7 @@ func SyncCfgInit(log *log.Logger, awsSession *session.Session, secretPrefix, wat
|
||||
log.Println("AWS Secrets Manager : Checking for remote updates")
|
||||
|
||||
// Do the initial sync before starting file watch to download any existing configs.
|
||||
err := SyncCfgDir(log, awsSession, secretPrefix, watchDir, localfiles)
|
||||
err := SyncCfgDir(log, awsSession, secretPrefix, watchDir, localfiles)
|
||||
if err != nil {
|
||||
log.Printf("AWS Secrets Manager : Remote sync error - %+v", err)
|
||||
}
|
||||
@ -82,7 +81,7 @@ func SyncCfgDir(log *log.Logger, awsSession *session.Session, secretPrefix, watc
|
||||
for _, s := range res.SecretList {
|
||||
|
||||
// Skip any secret that does not have a matching prefix.
|
||||
if !strings.HasPrefix(*s.Name, secretPrefix) {
|
||||
if !strings.HasPrefix(*s.Name, secretPrefix) {
|
||||
continue
|
||||
}
|
||||
|
||||
@ -192,7 +191,7 @@ func handleWatchCfgEvent(log *log.Logger, awsSession *session.Session, secretPre
|
||||
|
||||
// Restore secret after it was already previously deleted.
|
||||
_, err = svc.RestoreSecret(&secretsmanager.RestoreSecretInput{
|
||||
SecretId: aws.String(secretID),
|
||||
SecretId: aws.String(secretID),
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "file watcher failed to restore secret %s for %s", secretID, event.Name)
|
||||
@ -205,7 +204,7 @@ func handleWatchCfgEvent(log *log.Logger, awsSession *session.Session, secretPre
|
||||
|
||||
// If where was a resource exists error for create, then need to update the secret instead.
|
||||
_, err = svc.UpdateSecret(&secretsmanager.UpdateSecretInput{
|
||||
SecretId: aws.String(secretID),
|
||||
SecretId: aws.String(secretID),
|
||||
SecretString: aws.String(string(dat)),
|
||||
})
|
||||
if err != nil {
|
||||
@ -225,7 +224,7 @@ func handleWatchCfgEvent(log *log.Logger, awsSession *session.Session, secretPre
|
||||
|
||||
// Create the new entry in AWS Secret Manager for the file.
|
||||
_, err := svc.DeleteSecret(&secretsmanager.DeleteSecretInput{
|
||||
SecretId: aws.String(secretID),
|
||||
SecretId: aws.String(secretID),
|
||||
|
||||
// (Optional) Specifies that the secret is to be deleted without any recovery
|
||||
// window. You can't use both this parameter and the RecoveryWindowInDays parameter
|
||||
|
@ -3,9 +3,6 @@ package devops
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/sethgrid/pester"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
@ -33,15 +30,6 @@ func EcsServiceTaskInit(log *log.Logger, awsSession *session.Session) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
res, err := pester.Get("http://169.254.170.2/v2/metadata")
|
||||
if err != nil {
|
||||
fmt.Println("http://169.254.170.2/v2/metadata failed", err.Error())
|
||||
} else {
|
||||
dat, _ := ioutil.ReadAll(res.Body)
|
||||
res.Body.Close()
|
||||
fmt.Println("http://169.254.170.2/v2/metadata, OK", string(dat))
|
||||
}
|
||||
|
||||
var zoneArecNames = map[string][]string{}
|
||||
if v := os.Getenv("ROUTE53_ZONES"); v != "" {
|
||||
dat, err := base64.RawURLEncoding.DecodeString(v)
|
||||
@ -241,6 +229,15 @@ func RegisterEcsServiceTasksRoute53(log *log.Logger, awsSession *session.Session
|
||||
}
|
||||
|
||||
/*
|
||||
res, err := pester.Get("http://169.254.170.2/v2/metadata")
|
||||
if err != nil {
|
||||
fmt.Println("http://169.254.170.2/v2/metadata failed", err.Error())
|
||||
} else {
|
||||
dat, _ := ioutil.ReadAll(res.Body)
|
||||
res.Body.Close()
|
||||
fmt.Println("http://169.254.170.2/v2/metadata, OK", string(dat))
|
||||
}
|
||||
|
||||
http://169.254.170.2/v2/metadata,
|
||||
|
||||
{
|
||||
|
@ -19,7 +19,7 @@ import (
|
||||
|
||||
// Headers
|
||||
const (
|
||||
HeaderUpgrade = "Upgrade"
|
||||
HeaderUpgrade = "Upgrade"
|
||||
HeaderXForwardedFor = "X-Forwarded-For"
|
||||
HeaderXForwardedProto = "X-Forwarded-Proto"
|
||||
HeaderXForwardedProtocol = "X-Forwarded-Protocol"
|
||||
|
Reference in New Issue
Block a user