Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
b11f8d9
feat(cli): release check registered components: convo + partial state
sicoyle Aug 5, 2025
ab0619d
fix: add state components working properly with cli
sicoyle Aug 5, 2025
629dad1
feat: add pubsub component checks plus missing metadata files
sicoyle Aug 5, 2025
0c14def
feat: add secretstores and start on bindings
sicoyle Aug 6, 2025
4ec9db8
feat: add bindings
sicoyle Aug 6, 2025
4639640
feat: add crypto, lock, nameresolution comps to my setup and fix them up
sicoyle Aug 7, 2025
204f64f
style: rename file to what it should be
sicoyle Aug 7, 2025
c76ce88
feat: add middleware components to cli too
sicoyle Aug 7, 2025
4c9cfdb
style: clean up sam logs
sicoyle Aug 7, 2025
10e3174
style: add allllll other component types
sicoyle Aug 7, 2025
0d101e6
Merge branch 'main' into endgame-task-1.16-comp-registration
sicoyle Aug 7, 2025
556437c
fix: make build happy
sicoyle Aug 7, 2025
cea8dd2
fix(build): update to add newline i removed on accident
sicoyle Aug 7, 2025
2132832
style: ensure we use proper types in metadata files
sicoyle Aug 7, 2025
305a1d3
style: update metadata files for the analyzer to be happy
sicoyle Aug 8, 2025
7e7a7ae
fix: make metadata analyzer happy
sicoyle Aug 8, 2025
2842f7a
fix(rethink): support tls config with a workaround to make metadata a…
sicoyle Aug 8, 2025
0b616ef
style: rm extra quote
sicoyle Aug 8, 2025
443536f
style: make linter happy
sicoyle Aug 8, 2025
dd8ee7e
style: go back to old crypto nameing
sicoyle Aug 8, 2025
1f5262c
fix: last fixes for gcp pubsub bindingg
sicoyle Aug 8, 2025
94cb681
style: fix for metadata analyzer
sicoyle Aug 8, 2025
559f12a
style: appease linter
sicoyle Aug 8, 2025
ef4a474
revert: checkout state dir from main since in diff pr now
sicoyle Aug 11, 2025
7e19011
revert: checkout bindings dir from main since in diff pr now
sicoyle Aug 11, 2025
6f1ca96
revert: checkout nameresolution dir from main since in diff pr now
sicoyle Aug 11, 2025
e4da01b
revert: checkout middleware dir from main since in diff pr now
sicoyle Aug 11, 2025
5b4b3b0
revert: checkout ps dir from main since in diff pr now
sicoyle Aug 11, 2025
e3f9f16
fix: grab latest from master and reset these files to updated master
sicoyle Aug 11, 2025
e1371c6
revert: checkout lock + crypto dir from main since in diff pr now
sicoyle Aug 11, 2025
968cc23
revert: checkout secretstore dir from main since in diff pr now
sicoyle Aug 11, 2025
c0213e2
fix: clean up other changes moved to other prs
sicoyle Aug 11, 2025
8123429
style: few fixes after clean up on pr
sicoyle Aug 11, 2025
dfa1f29
Merge branch 'main' into endgame-task-1.16-comp-registration
sicoyle Aug 11, 2025
ce78278
Merge branch 'main' into endgame-task-1.16-comp-registration
yaron2 Aug 18, 2025
db64e28
Merge branch 'main' into endgame-task-1.16-comp-registration
sicoyle Aug 22, 2025
8de25d6
Merge branch 'main' into endgame-task-1.16-comp-registration
yaron2 Aug 22, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fix: grab latest from master and reset these files to updated master
Signed-off-by: Samantha Coyle <[email protected]>
  • Loading branch information
sicoyle committed Aug 11, 2025
commit e3f9f167754fc36deff34a84835b5e84819df2ae
2 changes: 1 addition & 1 deletion bindings/azure/servicebusqueues/servicebusqueues.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ func (a *AzureServiceBusQueues) Init(ctx context.Context, metadata bindings.Meta
return err
}

a.client, err = impl.NewClient(a.metadata, metadata.Properties)
a.client, err = impl.NewClient(a.metadata, metadata.Properties, a.logger)
if err != nil {
return err
}
Expand Down
43 changes: 36 additions & 7 deletions bindings/gcp/bucket/bucket.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,13 +110,7 @@ func (g *GCPStorage) Init(ctx context.Context, metadata bindings.Metadata) error
return err
}

b, err := json.Marshal(m)
if err != nil {
return err
}

clientOptions := option.WithCredentialsJSON(b)
client, err := storage.NewClient(ctx, clientOptions)
client, err := g.getClient(ctx, m)
if err != nil {
return err
}
Expand All @@ -127,6 +121,41 @@ func (g *GCPStorage) Init(ctx context.Context, metadata bindings.Metadata) error
return nil
}

func (g *GCPStorage) getClient(ctx context.Context, m *gcpMetadata) (*storage.Client, error) {
var client *storage.Client
var err error

if m.Bucket == "" {
return nil, errors.New("missing property `bucket` in metadata")
}
if m.ProjectID == "" {
return nil, errors.New("missing property `project_id` in metadata")
}

// Explicit authentication
if m.PrivateKeyID != "" {
var b []byte
b, err = json.Marshal(m)
if err != nil {
return nil, err
}

clientOptions := option.WithCredentialsJSON(b)
client, err = storage.NewClient(ctx, clientOptions)
if err != nil {
return nil, err
}
} else {
// Implicit authentication, using GCP Application Default Credentials (ADC)
// Credentials search order: https://cloud.google.com/docs/authentication/application-default-credentials#order
client, err = storage.NewClient(ctx)
if err != nil {
return nil, err
}
}
return client, nil
}

func (g *GCPStorage) parseMetadata(meta bindings.Metadata) (*gcpMetadata, error) {
m := gcpMetadata{}
err := kitmd.DecodeMetadata(meta.Properties, &m)
Expand Down
25 changes: 25 additions & 0 deletions bindings/gcp/bucket/bucket_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ package bucket

import (
"encoding/json"
"errors"
"testing"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -234,6 +235,30 @@ func TestMergeWithRequestMetadata(t *testing.T) {
})
}

func TestInit(t *testing.T) {
t.Run("Init missing bucket from metadata", func(t *testing.T) {
m := bindings.Metadata{}
m.Properties = map[string]string{
"projectID": "my_project_id",
}
gs := GCPStorage{logger: logger.NewLogger("test")}
err := gs.Init(t.Context(), m)
require.Error(t, err)
assert.Equal(t, err, errors.New("missing property `bucket` in metadata"))
})

t.Run("Init missing projectID from metadata", func(t *testing.T) {
m := bindings.Metadata{}
m.Properties = map[string]string{
"bucket": "my_bucket",
}
gs := GCPStorage{logger: logger.NewLogger("test")}
err := gs.Init(t.Context(), m)
require.Error(t, err)
assert.Equal(t, err, errors.New("missing property `project_id` in metadata"))
})
}

func TestGetOption(t *testing.T) {
gs := GCPStorage{logger: logger.NewLogger("test")}
gs.metadata = &gcpMetadata{}
Expand Down
26 changes: 25 additions & 1 deletion bindings/redis/metadata.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,30 @@ authenticationProfiles:
secret reference
example: "KeFg23!"
default: ""
- name: sentinelUsername
type: string
required: false
description: |
Username for Redis Sentinel. Applicable only when "failover" is true, and
Redis Sentinel has authentication enabled. Defaults to empty.
example: "my-sentinel-username"
default: ""
url:
title: "Redis Sentinel authentication documentation"
url: "https://redis.io/docs/latest/operate/oss_and_stack/management/sentinel/#configuring-sentinel-instances-with-authentication"
- name: sentinelPassword
type: string
required: false
sensitive: true
description: |
Password for Redis Sentinel. Applicable only when "failover" is true, and
Redis Sentinel has authentication enabled. Use secretKeyRef for
secret reference. Defaults to empty.
example: "KeFg23!"
default: ""
url:
title: "Redis Sentinel authentication documentation"
url: "https://redis.io/docs/latest/operate/oss_and_stack/management/sentinel/#configuring-sentinel-instances-with-authentication"
metadata:
- name: redisHost
required: true
Expand Down Expand Up @@ -104,7 +128,7 @@ metadata:
required: false
description: |
The Redis sentinel master name. Required when "failover" is enabled.
example: "127.0.0.1:6379"
example: "mymaster"
url:
title: "Redis Sentinel documentation"
url: "https://redis.io/docs/manual/sentinel/"
Expand Down
22 changes: 22 additions & 0 deletions middleware/http/oauth2/oauth2_middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"net/http"
"net/url"
"reflect"
"regexp"
"strings"

"github.com/fasthttp-contrib/sessions"
Expand All @@ -42,6 +43,9 @@ type oAuth2MiddlewareMetadata struct {
AuthHeaderName string `json:"authHeaderName" mapstructure:"authHeaderName"`
RedirectURL string `json:"redirectURL" mapstructure:"redirectURL"`
ForceHTTPS string `json:"forceHTTPS" mapstructure:"forceHTTPS"`
PathFilter string `json:"pathFilter" mapstructure:"pathFilter"`

pathFilterRegex *regexp.Regexp
}

// NewOAuth2Middleware returns a new oAuth2 middleware.
Expand Down Expand Up @@ -84,6 +88,15 @@ func (m *Middleware) GetHandler(ctx context.Context, metadata middleware.Metadat

return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if meta.pathFilterRegex != nil {
matched := meta.pathFilterRegex.MatchString(r.URL.Path)
if !matched {
m.logger.Debugf("PathFilter %s didn't match %s! Skipping!", meta.PathFilter, r.URL.Path)
next.ServeHTTP(w, r)
return
}
}

session := sessions.Start(w, r)

if session.GetString(meta.AuthHeaderName) != "" {
Expand Down Expand Up @@ -153,6 +166,15 @@ func (m *Middleware) getNativeMetadata(metadata middleware.Metadata) (*oAuth2Mid
if err != nil {
return nil, err
}

if middlewareMetadata.PathFilter != "" {
rx, err := regexp.Compile(middlewareMetadata.PathFilter)
if err != nil {
return nil, err
}
middlewareMetadata.pathFilterRegex = rx
}

return &middlewareMetadata, nil
}

Expand Down
49 changes: 49 additions & 0 deletions middleware/http/oauth2/oauth2_middleware_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,52 @@ func TestOAuth2CreatesAuthorizationHeaderWhenInSessionState(t *testing.T) {

assert.Equal(t, "Bearer abcd", r.Header.Get("someHeader"))
}

func TestOAuth2CreatesAuthorizationHeaderGetNativeMetadata(t *testing.T) {
var metadata middleware.Metadata
metadata.Properties = map[string]string{
"clientID": "testId",
"clientSecret": "testSecret",
"scopes": "ascope",
"authURL": "https://idp:9999",
"tokenURL": "https://idp:9999",
"redirectUrl": "https://localhost:9999",
"authHeaderName": "someHeader",
}

log := logger.NewLogger("oauth2.test")
oauth2Middleware, ok := NewOAuth2Middleware(log).(*Middleware)
require.True(t, ok)

tc := []struct {
name string
pathFilter string
wantErr bool
}{
{name: "empty pathFilter", pathFilter: "", wantErr: false},
{name: "wildcard pathFilter", pathFilter: ".*", wantErr: false},
{name: "api path pathFilter", pathFilter: "/api/v1/users", wantErr: false},
{name: "debug endpoint pathFilter", pathFilter: "^/debug/?$", wantErr: false},
{name: "user id pathFilter", pathFilter: "^/user/[0-9]+$", wantErr: false},
{name: "invalid wildcard pathFilter", pathFilter: "*invalid", wantErr: true},
{name: "unclosed parenthesis pathFilter", pathFilter: "invalid(", wantErr: true},
{name: "unopened parenthesis pathFilter", pathFilter: "invalid)", wantErr: true},
}

for _, tt := range tc {
t.Run(tt.name, func(t *testing.T) {
metadata.Properties["pathFilter"] = tt.pathFilter
nativeMetadata, err := oauth2Middleware.getNativeMetadata(metadata)
if tt.wantErr {
require.Error(t, err)
} else {
require.NoError(t, err)
if tt.pathFilter != "" {
require.NotNil(t, nativeMetadata.pathFilterRegex)
} else {
require.Nil(t, nativeMetadata.pathFilterRegex)
}
}
})
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"net/http"
"net/url"
"reflect"
"regexp"
"strings"
"time"

Expand All @@ -43,6 +44,9 @@ type oAuth2ClientCredentialsMiddlewareMetadata struct {
HeaderName string `json:"headerName" mapstructure:"headerName"`
EndpointParamsQuery string `json:"endpointParamsQuery,omitempty" mapstructure:"endpointParamsQuery"`
AuthStyle int `json:"authStyle" mapstructure:"authStyle"`
PathFilter string `json:"pathFilter" mapstructure:"pathFilter"`

pathFilterRegex *regexp.Regexp
}

// TokenProviderInterface provides a common interface to Mock the Token retrieval in unit tests.
Expand All @@ -69,7 +73,7 @@ type Middleware struct {
tokenProvider TokenProviderInterface
}

// GetHandler retruns the HTTP handler provided by the middleware.
// GetHandler returns the HTTP handler provided by the middleware.
func (m *Middleware) GetHandler(_ context.Context, metadata middleware.Metadata) (func(next http.Handler) http.Handler, error) {
meta, err := m.getNativeMetadata(metadata)
if err != nil {
Expand Down Expand Up @@ -98,27 +102,38 @@ func (m *Middleware) GetHandler(_ context.Context, metadata middleware.Metadata)
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var headerValue string

// Check if valid token is in the cache
cachedToken, found := m.tokenCache.Get(cacheKey)
if !found {
m.log.Debugf("Cached token not found, try get one")

token, err := m.tokenProvider.GetToken(r.Context(), conf)
if err != nil {
m.log.Errorf("Error acquiring token: %s", err)
if meta.pathFilterRegex != nil {
matched := meta.pathFilterRegex.MatchString(r.URL.Path)
if !matched {
m.log.Debugf("PathFilter %s didn't match %s! Skipping!", meta.PathFilter, r.URL.Path)
next.ServeHTTP(w, r)
return
}
}

tokenExpirationDuration := time.Until(token.Expiry)
m.log.Debugf("Token expires at %s (%s from now)", token.Expiry, tokenExpirationDuration)

headerValue = token.Type() + " " + token.AccessToken
m.tokenCache.Set(cacheKey, headerValue, tokenExpirationDuration)
} else {
// Check if valid token is in the cache
cachedToken, found := m.tokenCache.Get(cacheKey)
if found {
m.log.Debugf("Cached token found for key %s", cacheKey)
headerValue = cachedToken.(string)
r.Header.Add(meta.HeaderName, headerValue)
next.ServeHTTP(w, r)
return
}

m.log.Infof("Cached token not found, attempting to retrieve a new one")
token, err := m.tokenProvider.GetToken(r.Context(), conf)
if err != nil {
m.log.Errorf("Error acquiring token: %s", err)
return
}

tokenExpirationDuration := time.Until(token.Expiry)
m.log.Infof("Token expires at %s (%s from now)", token.Expiry, tokenExpirationDuration)

headerValue = token.Type() + " " + token.AccessToken
m.tokenCache.Set(cacheKey, headerValue, tokenExpirationDuration)

r.Header.Add(meta.HeaderName, headerValue)
next.ServeHTTP(w, r)
})
Expand All @@ -142,6 +157,14 @@ func (m *Middleware) getNativeMetadata(metadata middleware.Metadata) (*oAuth2Cli
m.checkMetadataValueExists(&errorString, &middlewareMetadata.Scopes, "scopes")
m.checkMetadataValueExists(&errorString, &middlewareMetadata.TokenURL, "tokenURL")

if middlewareMetadata.PathFilter != "" {
rx, err := regexp.Compile(middlewareMetadata.PathFilter)
if err != nil {
errorString += "Parameter 'pathFilter' is not a valid regex: " + err.Error() + ". "
}
middlewareMetadata.pathFilterRegex = rx
}

// Value-check AuthStyle
if middlewareMetadata.AuthStyle < 0 || middlewareMetadata.AuthStyle > 2 {
errorString += fmt.Sprintf("Parameter 'authStyle' can only have the values 0,1,2. Received: '%d'. ", middlewareMetadata.AuthStyle)
Expand Down
Loading
Loading