config integration

begin cognito config integration
This commit is contained in:
jay brown
2025-04-09 17:19:19 -07:00
parent c1a17d89bf
commit 4f40a7e6ea
13 changed files with 193 additions and 445 deletions
@@ -8,6 +8,7 @@ import (
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
"queryorchestration/internal/cognitoauth" // Replace with your actual package import path
)
+6 -6
View File
@@ -34,7 +34,6 @@ import (
"queryorchestration/internal/server/api"
"queryorchestration/internal/serviceconfig/queue/clientsync"
"queryorchestration/internal/serviceconfig/queue/queryversionsync"
"queryorchestration/internal/serviceconfig/rbac"
"github.com/getkin/kin-openapi/openapi3"
_ "github.com/lib/pq"
@@ -106,12 +105,13 @@ func main() {
os.Exit(1)
}
// note initialize cognito config here
// Initialize the rbac config here since only the API service needs it
errorGettingAuthProvider := rbac.InitializeAuthProvider(&cfg.AuthConfig)
if errorGettingAuthProvider != nil {
slog.Error(errorGettingAuthProvider.Error())
os.Exit(1)
}
//errorGettingAuthProvider := rbac.InitializeAuthProvider(&cfg.AuthConfig)
//if errorGettingAuthProvider != nil {
// slog.Error(errorGettingAuthProvider.Error())
// os.Exit(1)
//}
server, err := api.New(ctx, cfg)
if err != nil {
+2 -2
View File
@@ -11,7 +11,7 @@ import (
)
// RegisterRoutes registers all authentication-related routes to the Echo engine
func RegisterRoutes(e *echo.Echo, config *Config) {
func RegisterRoutes(e *echo.Echo, config *CognitoConfig) {
// Register the login route - the middleware will handle this
e.GET(config.LoginPath, func(c echo.Context) error {
// This is handled by the middleware
@@ -53,7 +53,7 @@ func RegisterRoutes(e *echo.Echo, config *Config) {
}
// HomeHandler implements a simple home page that shows auth status and available endpoints
func HomeHandler(c echo.Context, config *Config) error {
func HomeHandler(c echo.Context, config *CognitoConfig) error {
// Create a list of all registered routes
var endpoints []string
+15 -12
View File
@@ -8,27 +8,30 @@ import (
"strings"
)
// Config holds the configuration for AWS Cognito
// CognitoConfig holds the configuration for AWS Cognito
// Contains all necessary parameters to interact with Cognito endpoints
type Config struct {
ClientID string // OAuth2 client ID registered with Cognito
type CognitoConfig struct {
RedirectURI string // URL where Cognito redirects after authentication
TokenURL string // Cognito endpoint for token operations
JwksURL string // URL for JSON Web Key Set (for token verification)
UserPoolID string // Cognito User Pool ID
AuthURL string // Cognito authorization endpoint for initiating login
ClientSecret string // Client secret for authenticated clients
Region string // AWS region where the Cognito User Pool is located
LoginPath string // Path for initiating login
CallbackPath string // Path for OAuth callback
HomePath string // Path for home page
LogoutPath string // Path for logout
Logger *slog.Logger // Logger instance
RoutePermissions map[string][]string // Map of routes to required permissions
// annotated vars
Region string `env:"COGNITO_REGION" envDefault:"us-east-2"`
UserPoolID string `env:"COGNITO_USER_POOL_ID" required:"true"`
ClientSecret string `env:"COGNITO_CLIENT_SECRET" required:"true"`
Domain string `env:"COGNITO_DOMAIN" required:"true"`
ClientID string `env:"COGNITO_CLIENT_ID" required:"true"`
}
// NewConfigFromEnv creates a new Config from environment variables
func NewConfigFromEnv(baseURL string, logger *slog.Logger) *Config {
// NewConfigFromEnv creates a new CognitoConfig from environment variables
func NewConfigFromEnv(baseURL string, logger *slog.Logger) *CognitoConfig {
// Set default logger if not provided
if logger == nil {
var logLevel slog.Level
@@ -94,7 +97,7 @@ func NewConfigFromEnv(baseURL string, logger *slog.Logger) *Config {
// Sanitize base URL (remove trailing slash)
baseURL = strings.TrimSuffix(baseURL, "/")
config := &Config{
config := &CognitoConfig{
ClientID: os.Getenv("COGNITO_CLIENT_ID"),
ClientSecret: os.Getenv("COGNITO_CLIENT_SECRET"),
RedirectURI: baseURL + callbackPath,
@@ -115,8 +118,8 @@ func NewConfigFromEnv(baseURL string, logger *slog.Logger) *Config {
return config
}
func (c *Config) PrettyPrint() {
fmt.Printf("Config:\n")
func (c *CognitoConfig) PrettyPrint() {
fmt.Printf("CognitoConfig:\n")
fmt.Printf(" ClientID: %s\n", c.ClientID)
fmt.Printf(" ClientSecret: %s\n", c.ClientSecret)
fmt.Printf(" RedirectURI: %s\n", c.RedirectURI)
@@ -138,6 +141,6 @@ func (c *Config) PrettyPrint() {
}
// SetRoutePermissions sets the route permissions map
func (c *Config) SetRoutePermissions(permissions map[string][]string) {
func (c *CognitoConfig) SetRoutePermissions(permissions map[string][]string) {
c.RoutePermissions = permissions
}
+4 -4
View File
@@ -15,7 +15,7 @@ import (
// initiateLoginWithPKCE generates PKCE code challenge and redirects to Cognito
// This function starts the OAuth authorization flow with PKCE
func initiateLoginWithPKCE(c echo.Context, config *Config) error {
func initiateLoginWithPKCE(c echo.Context, config *CognitoConfig) error {
// Generate random state parameter to prevent CSRF
state, err := generateRandomString(32)
if err != nil {
@@ -63,7 +63,7 @@ func initiateLoginWithPKCE(c echo.Context, config *Config) error {
// exchangeCodeForTokensWithPKCE exchanges the authorization code for tokens using PKCE
// Called during the OAuth callback flow to get tokens from the authorization code
// Makes an HTTP request to Cognito's token endpoint to perform this exchange
func exchangeCodeForTokensWithPKCE(authCode, codeVerifier string, config Config) (*TokenResponse, error) {
func exchangeCodeForTokensWithPKCE(authCode, codeVerifier string, config CognitoConfig) (*TokenResponse, error) {
data := url.Values{}
data.Set("grant_type", "authorization_code")
data.Set("client_id", config.ClientID)
@@ -118,7 +118,7 @@ func exchangeCodeForTokensWithPKCE(authCode, codeVerifier string, config Config)
// handleOAuthCallback handles the OAuth 2.0 authorization code flow callback with PKCE
// Called when Cognito redirects back to our application with an authorization code
// Exchanges the code for tokens, verifies them, and redirects to home page with token in cookie
func handleOAuthCallback(c echo.Context, config *Config) error {
func handleOAuthCallback(c echo.Context, config *CognitoConfig) error {
// Extract the authorization code and state
code := c.QueryParam("code")
if code == "" {
@@ -228,7 +228,7 @@ func handleOAuthCallback(c echo.Context, config *Config) error {
}
// LogoutHandler handles the logout process by clearing the auth cookie
func LogoutHandler(c echo.Context, config *Config) error {
func LogoutHandler(c echo.Context, config *CognitoConfig) error {
// Clear the token cookie
cookie := new(http.Cookie)
cookie.Name = "auth_token"
+2 -2
View File
@@ -10,7 +10,7 @@ import (
// TokenValidationMiddleware verifies JWT tokens efficiently
// This is the primary middleware that handles both authentication and authorization
// Applied to all routes to enforce security requirements
func TokenValidationMiddleware(config *Config) echo.MiddlewareFunc {
func TokenValidationMiddleware(config *CognitoConfig) echo.MiddlewareFunc {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
requestPath := c.Request().URL.Path
@@ -106,7 +106,7 @@ func TokenValidationMiddleware(config *Config) echo.MiddlewareFunc {
}
// JWTAuthMiddleware checks for JWT token in cookies and adds it to the Authorization header
func JWTAuthMiddleware(config *Config) echo.MiddlewareFunc {
func JWTAuthMiddleware(config *CognitoConfig) echo.MiddlewareFunc {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
// Skip for login and callback paths
+1 -1
View File
@@ -17,7 +17,7 @@ import (
// verifyToken verifies the JWT token and returns its claims
// Used during both OAuth callback and subsequent API requests with bearer token
// Verifies signature, expiration, issuer, and other JWT claims
func verifyToken(tokenString string, keySet jwk.Set, config Config) (map[string]interface{}, error) {
func verifyToken(tokenString string, keySet jwk.Set, config CognitoConfig) (map[string]interface{}, error) {
region := config.Region
issuer := fmt.Sprintf("https://cognito-idp.%s.amazonaws.com/%s", region, config.UserPoolID)
+11 -11
View File
@@ -84,14 +84,14 @@ func checkPermissions(path string, userGroups []string, routePermissions map[str
return false, requiredGroups
}
// Helper function to mask sensitive values
// Used for logging sensitive information like client IDs
func maskString(s string) string {
if s == "" {
return "<not set>"
}
if len(s) <= 8 {
return "****"
}
return s[:4] + "..." + s[len(s)-4:]
}
//// Helper function to mask sensitive values
//// Used for logging sensitive information like client IDs
//func maskString(s string) string {
// if s == "" {
// return "<not set>"
// }
// if len(s) <= 8 {
// return "****"
// }
// return s[:4] + "..." + s[len(s)-4:]
//}
@@ -0,0 +1,147 @@
package cognitoauth
import (
"fmt"
"log"
"log/slog"
"os"
"strings"
)
// CognitoConfig holds the configuration for AWS Cognito
// Contains all necessary parameters to interact with Cognito endpoints
type CognitoConfig struct {
// annotated vars
Region string `env:"COGNITO_REGION" envDefault:"us-east-2"`
UserPoolID string `env:"COGNITO_USER_POOL_ID,required,notEmpty"`
ClientSecret string `env:"COGNITO_CLIENT_SECRET,required,notEmpty"`
Domain string `env:"COGNITO_DOMAIN,required,notEmpty"`
ClientID string `env:"COGNITO_CLIENT_ID,required,notEmpty"`
RedirectURI string // URL where Cognito redirects after authentication
TokenURL string // Cognito endpoint for token operations
JwksURL string // URL for JSON Web Key Set (for token verification)
AuthURL string // Cognito authorization endpoint for initiating login
LoginPath string // Path for initiating login
CallbackPath string // Path for OAuth callback
HomePath string // Path for home page
LogoutPath string // Path for logout
AuthLogger *slog.Logger // Logger instance ( normally just the same logger as main)
RoutePermissions map[string][]string // Map of routes to required permissions
}
// InitializeConfig creates a new CognitoConfig from environment variables
// and sets the values that are computed from other values
func InitializeConfig(baseURL string, logger *slog.Logger) *CognitoConfig {
// Set default logger if not provided
if logger == nil {
var logLevel slog.Level
if os.Getenv("DEBUG") == "true" {
logLevel = slog.LevelDebug
} else {
logLevel = slog.LevelInfo
}
logHandler := slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
Level: logLevel,
})
logger = slog.New(logHandler)
}
// Set paths with defaults
loginPath := os.Getenv("COGNITO_LOGIN_PATH")
if loginPath == "" {
loginPath = "/login"
}
callbackPath := os.Getenv("COGNITO_CALLBACK_PATH")
if callbackPath == "" {
callbackPath = "/login-callback"
}
homePath := os.Getenv("COGNITO_HOME_PATH")
if homePath == "" {
homePath = "/home"
}
logoutPath := os.Getenv("COGNITO_LOGOUT_PATH")
if logoutPath == "" {
logoutPath = "/logout"
}
// Get AWS region with fallback
region := os.Getenv("AWS_REGION")
if region == "" {
region = "us-east-2" // Fallback to default value
}
// Get User Pool ID with fallback
userPoolID := os.Getenv("COGNITO_USER_POOL_ID")
if userPoolID == "" {
userPoolID = "" // No default, will need to be provided
logger.Warn("COGNITO_USER_POOL_ID environment variable is not set")
}
// Get Cognito domain
domain := os.Getenv("COGNITO_DOMAIN")
if domain == "" {
//logger.Warn("COGNITO_DOMAIN environment variable is not set, using default")
//// Use the user pool ID directly as part of the domain
//domain = fmt.Sprintf("%s.auth.%s.amazoncognito.com", userPoolID, region)
log.Fatalf("COGNITO_DOMAIN environment variable is not set")
}
// Ensure domain format is correct (no protocol prefix)
domain = strings.TrimPrefix(domain, "https://")
domain = strings.TrimPrefix(domain, "http://")
// Sanitize base URL (remove trailing slash)
baseURL = strings.TrimSuffix(baseURL, "/")
config := &CognitoConfig{
ClientID: os.Getenv("COGNITO_CLIENT_ID"),
ClientSecret: os.Getenv("COGNITO_CLIENT_SECRET"),
RedirectURI: baseURL + callbackPath,
TokenURL: fmt.Sprintf("https://%s/oauth2/token", domain),
AuthURL: fmt.Sprintf("https://%s/oauth2/authorize", domain),
JwksURL: fmt.Sprintf("https://cognito-idp.%s.amazonaws.com/%s/.well-known/jwks.json", region, userPoolID),
UserPoolID: userPoolID,
Region: region,
LoginPath: loginPath,
CallbackPath: callbackPath,
HomePath: homePath,
LogoutPath: logoutPath,
AuthLogger: logger,
RoutePermissions: make(map[string][]string),
}
config.PrettyPrint()
return config
}
func (c *CognitoConfig) PrettyPrint() {
fmt.Printf("CognitoConfig:\n")
fmt.Printf(" ClientID: %s\n", c.ClientID)
fmt.Printf(" ClientSecret: %s\n", c.ClientSecret)
fmt.Printf(" RedirectURI: %s\n", c.RedirectURI)
fmt.Printf(" TokenURL: %s\n", c.TokenURL)
fmt.Printf(" AuthURL: %s\n", c.AuthURL)
fmt.Printf(" JwksURL: %s\n", c.JwksURL)
fmt.Printf(" UserPoolID: %s\n", c.UserPoolID)
fmt.Printf(" Region: %s\n", c.Region)
fmt.Printf(" LoginPath: %s\n", c.LoginPath)
fmt.Printf(" CallbackPath: %s\n", c.CallbackPath)
fmt.Printf(" HomePath: %s\n", c.HomePath)
fmt.Printf(" LogoutPath: %s\n", c.LogoutPath)
// pretty print the route permissions map
for route, permissions := range c.RoutePermissions {
fmt.Printf(" Route: %s, Permissions: %v\n", route, permissions)
}
}
// SetRoutePermissions sets the route permissions map
func (c *CognitoConfig) SetRoutePermissions(permissions map[string][]string) {
c.RoutePermissions = permissions
}
+4 -4
View File
@@ -4,12 +4,11 @@ import (
"errors"
"fmt"
"log/slog"
"queryorchestration/internal/serviceconfig/cognitoauth"
"reflect"
"strings"
"sync"
"queryorchestration/internal/serviceconfig/rbac"
"queryorchestration/internal/serviceconfig/aws"
"queryorchestration/internal/serviceconfig/database"
"queryorchestration/internal/serviceconfig/logger"
@@ -33,7 +32,8 @@ type BaseConfig struct {
Pwd string `env:"PWD,required,notEmpty"`
rbac.AuthConfig
//rbac.AuthConfig
cognitoauth.CognitoConfig
logger.LogConfig
observability.ObsConfig
database.DBConfig
@@ -52,7 +52,7 @@ type ConfigProvider interface {
logger.ConfigProvider
aws.ConfigProvider
queue.ConfigProvider
rbac.ConfigProvider
//rbac.ConfigProvider
}
// Configuration Methods
-92
View File
@@ -1,92 +0,0 @@
package rbac
import (
"fmt"
"log/slog"
"queryorchestration/internal/rbac"
)
// AuthConfig holds the RBAC configuration and KeyProvider
type AuthConfig struct {
// cognito or local
AuthType string `env:"RBAC_PROVIDER" envDefault:"local"`
// Cognito Config
CognitoRegion string `env:"COGNITO_REGION" envDefault:"us-east-1"`
CognitoUserPoolID string `env:"COGNITO_USER_POOL_ID"`
// Local Key Config
PrivateKeyPath string `env:"RBAC_PRIVATE_KEY_PATH" envDefault:"./public_key.pem"`
PublicKeyPath string `env:"RBAC_PUBLIC_KEY_PATH" envDefault:"./private_key.pem"`
// Actual provider - can be either local or cognito
AuthProvider rbac.KeyProvider
}
// ConfigProvider interface defines the methods required for RBAC configuration
type ConfigProvider interface {
//Initialize() error
GetKeyProvider() rbac.KeyProvider
PrintAuthConfig()
}
// GetKeyProvider returns the configured KeyProvider
func (r *AuthConfig) GetKeyProvider() rbac.KeyProvider {
return r.AuthProvider
}
func InitializeAuthProvider(config *AuthConfig) error {
return config.InitializeAuthProvider()
}
// InitializeAuthProvider initializes the appropriate KeyProvider based on configuration
func (r *AuthConfig) InitializeAuthProvider() error {
switch r.AuthType {
case "local":
if r.PrivateKeyPath == "" || r.PublicKeyPath == "" {
return fmt.Errorf("local key provider requires both private and public key paths")
}
r.AuthProvider = rbac.NewLocalKeyProvider(r.PrivateKeyPath, r.PublicKeyPath)
slog.Info("RBAC initialized with local key provider")
case "cognito":
if r.CognitoUserPoolID == "" {
return fmt.Errorf("cognito provider requires user pool ID")
}
r.AuthProvider = rbac.NewCognitoKeyProvider(r.CognitoRegion, r.CognitoUserPoolID)
slog.Info("RBAC initialized with Cognito key provider")
default:
return fmt.Errorf("unknown RBAC provider type: %s", r.AuthType)
}
r.PrintAuthConfig()
return nil
}
// PrintAuthConfig logs the current configuration, masking sensitive values
func (r *AuthConfig) PrintAuthConfig() {
slog.Info("RBAC AuthConfig:",
"provider_type", r.AuthType,
"region", r.CognitoRegion,
"user_pool_id", r.CognitoUserPoolID,
"private_key_path", r.PrivateKeyPath,
"public_key_path", r.PublicKeyPath,
)
}
// Validate checks if the configuration is valid
func (r *AuthConfig) Validate() error {
switch r.AuthType {
case "local":
if r.PrivateKeyPath == "" || r.PublicKeyPath == "" {
return fmt.Errorf("local key provider requires both private and public key paths")
}
case "cognito":
if r.CognitoUserPoolID == "" {
return fmt.Errorf("cognito provider requires user pool ID")
}
default:
return fmt.Errorf("invalid provider type: %s", r.AuthType)
}
return nil
}
-311
View File
@@ -1,311 +0,0 @@
package rbac_test
import (
"crypto/rsa"
"os"
"testing"
"github.com/stretchr/testify/assert"
"queryorchestration/internal/serviceconfig/rbac"
)
// TestGetKeyProvider tests the GetKeyProvider method
func TestGetKeyProvider(t *testing.T) {
// Create a temporary directory for test key files
tmpDir, err := os.MkdirTemp("", "rbac-test")
if err != nil {
t.Fatalf("Failed to create temp dir: %v", err)
}
defer func(path string) {
err := os.RemoveAll(path)
if err != nil {
t.Fatalf("Failed to remove temp dir: %v", err)
}
}(tmpDir)
// Create temporary key files with minimal PEM format
privateKeyPath := tmpDir + "/private_key.pem"
publicKeyPath := tmpDir + "/public_key.pem"
// Write minimal PEM content to the key files
// These are not valid RSA keys, but that doesn't matter for this test
// as we're just testing that the config passes the paths correctly
err = os.WriteFile(privateKeyPath, []byte(`-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA0Gzk05Pbnb12O7O+vCrwY9oMsEsKkJZ1hnMvP4JXOa0beJAw
DgYKAAAAAAAAAAA=
-----END RSA PRIVATE KEY-----`), 0600)
if err != nil {
t.Fatalf("Failed to write private key: %v", err)
}
err = os.WriteFile(publicKeyPath, []byte(`-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0Gzk05Pbnb12O7O+vCrw
Y9oMsEsKkJZ1hnMvP4JXOa0beJAwOJosFh5kAAs=
-----END PUBLIC KEY-----`), 0600)
if err != nil {
t.Fatalf("Failed to write public key: %v", err)
}
// Create an AuthConfig with local provider
config := &rbac.AuthConfig{
AuthType: "local",
PrivateKeyPath: privateKeyPath,
PublicKeyPath: publicKeyPath,
}
// Since we can't successfully load invalid keys, we'll just test the GetKeyProvider method directly
// without initializing the provider
config.AuthProvider = &mockKeyProvider{} // Use our mock key provider
// Test GetKeyProvider
provider := config.GetKeyProvider()
assert.NotNil(t, provider, "GetKeyProvider should return a non-nil provider")
assert.Equal(t, &mockKeyProvider{}, provider, "Provider should match what we set")
}
// TestInitializeAuthProvider tests the InitializeAuthProvider function
func TestInitializeAuthProvider(t *testing.T) {
// Create a temporary directory for test key files
tmpDir, err := os.MkdirTemp("", "rbac-test")
if err != nil {
t.Fatalf("Failed to create temp dir: %v", err)
}
defer func(path string) {
err := os.RemoveAll(path)
if err != nil {
t.Fatalf("Failed to remove temp dir: %v", err)
}
}(tmpDir)
// Create temporary key files
privateKeyPath := tmpDir + "/private_key.pem"
publicKeyPath := tmpDir + "/public_key.pem"
// Write some dummy content to the key files - these are NOT valid keys
err = os.WriteFile(privateKeyPath, []byte(`-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA0Gzk05Pbnb12O7O+vCrwY9oMsEsKkJZ1hnMvP4JXOa0beJAw
DgYKAAAAAAAAAAA=
-----END RSA PRIVATE KEY-----`), 0600)
if err != nil {
t.Fatalf("Failed to write private key: %v", err)
}
err = os.WriteFile(publicKeyPath, []byte(`-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0Gzk05Pbnb12O7O+vCrw
Y9oMsEsKkJZ1hnMvP4JXOa0beJAwOJosFh5kAAs=
-----END PUBLIC KEY-----`), 0600)
if err != nil {
t.Fatalf("Failed to write public key: %v", err)
}
// Test cases for InitializeAuthProvider
testCases := []struct {
name string
config *rbac.AuthConfig
expectError bool
}{
{
name: "Missing local key paths",
config: &rbac.AuthConfig{
AuthType: "local",
},
expectError: true,
},
{
name: "Missing Cognito user pool ID",
config: &rbac.AuthConfig{
AuthType: "cognito",
CognitoRegion: "us-east-1",
// Missing user pool ID
},
expectError: true,
},
{
name: "Invalid auth type",
config: &rbac.AuthConfig{
AuthType: "invalid",
},
expectError: true,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
err := rbac.InitializeAuthProvider(tc.config)
if tc.expectError {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
})
}
}
// TestAuthConfigInitializeAuthProvider tests the AuthConfig method version of InitializeAuthProvider
func TestAuthConfigInitializeAuthProvider(t *testing.T) {
// Create a temporary directory for test key files
tmpDir, err := os.MkdirTemp("", "rbac-test")
if err != nil {
t.Fatalf("Failed to create temp dir: %v", err)
}
defer func(path string) {
err := os.RemoveAll(path)
if err != nil {
t.Fatalf("Failed to remove temp dir: %v", err)
}
}(tmpDir)
// Create temporary key files
privateKeyPath := tmpDir + "/private_key.pem"
publicKeyPath := tmpDir + "/public_key.pem"
// Write dummy PEM content to the key files
err = os.WriteFile(privateKeyPath, []byte(`-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA0Gzk05Pbnb12O7O+vCrwY9oMsEsKkJZ1hnMvP4JXOa0beJAw
DgYKAAAAAAAAAAA=
-----END RSA PRIVATE KEY-----`), 0600)
if err != nil {
t.Fatalf("Failed to write private key: %v", err)
}
err = os.WriteFile(publicKeyPath, []byte(`-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0Gzk05Pbnb12O7O+vCrw
Y9oMsEsKkJZ1hnMvP4JXOa0beJAwOJosFh5kAAs=
-----END PUBLIC KEY-----`), 0600)
if err != nil {
t.Fatalf("Failed to write public key: %v", err)
}
testCases := []struct {
name string
config *rbac.AuthConfig
expectError bool
}{
{
name: "Supplied local key paths",
config: &rbac.AuthConfig{
AuthType: "local",
// Missing key paths
PublicKeyPath: publicKeyPath,
PrivateKeyPath: privateKeyPath,
},
expectError: false,
},
{
name: "Missing Cognito user pool ID",
config: &rbac.AuthConfig{
AuthType: "cognito",
CognitoRegion: "us-east-1",
// Missing user pool ID
},
expectError: true,
},
{
name: "Invalid auth type",
config: &rbac.AuthConfig{
AuthType: "invalid",
},
expectError: true,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
err := tc.config.InitializeAuthProvider()
if tc.expectError {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
})
}
}
// TestPrintAuthConfig tests the PrintAuthConfig method
func TestPrintAuthConfig(t *testing.T) {
// Create an AuthConfig with some test values
config := &rbac.AuthConfig{
AuthType: "cognito",
CognitoRegion: "us-east-1",
CognitoUserPoolID: "us-east-1_TestPool",
PrivateKeyPath: "/path/to/private.pem",
PublicKeyPath: "/path/to/public.pem",
}
// Call PrintAuthConfig - there's no return value, so we're just ensuring it doesn't panic
config.PrintAuthConfig()
}
// TestValidate tests the Validate method
func TestValidate(t *testing.T) {
testCases := []struct {
name string
config *rbac.AuthConfig
expectError bool
}{
{
name: "Valid local config",
config: &rbac.AuthConfig{
AuthType: "local",
PrivateKeyPath: "/path/to/private.pem",
PublicKeyPath: "/path/to/public.pem",
},
expectError: false,
},
{
name: "Valid Cognito config",
config: &rbac.AuthConfig{
AuthType: "cognito",
CognitoRegion: "us-east-1",
CognitoUserPoolID: "us-east-1_TestPool",
},
expectError: false,
},
{
name: "Invalid auth type",
config: &rbac.AuthConfig{
AuthType: "invalid",
},
expectError: true,
},
{
name: "Missing local key paths",
config: &rbac.AuthConfig{
AuthType: "local",
// Missing key paths
},
expectError: true,
},
{
name: "Missing Cognito user pool ID",
config: &rbac.AuthConfig{
AuthType: "cognito",
CognitoRegion: "us-east-1",
// Missing user pool ID
},
expectError: true,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
err := tc.config.Validate()
if tc.expectError {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
})
}
}
// Mock key provider for testing
type mockKeyProvider struct{}
func (m *mockKeyProvider) GetPublicKey(kid string) (*rsa.PublicKey, error) {
return nil, nil
}