diff --git a/demo/.env_development b/demo/.env_development index d27abf42..305ea7ca 100644 --- a/demo/.env_development +++ b/demo/.env_development @@ -1,13 +1,26 @@ -export OVERMIND_NO_PORT=1 -export OPA_SERVER_URL=http://opa-agent:8887/v1/data/authz/allow -export ORCHESTRATOR_URL=http://0.0.0.0:8885 +OVERMIND_NO_PORT=1 +OPA_SERVER_URL=http://opa-agent:8887/v1/data/authz/allow -export ORCHESTRATOR_HOSTPORT=0.0.0.0:8885 -export HEXA_DEMO_URL=http://0.0.0.0:8886 -export HEXA_DEMO_CONFIG_URL=http://0.0.0.0:8889 -export ORCHESTRATOR_CONFIG_FILE=./deployments/hexaOrchestrator/config/config.json -export POSTGRES_DB=keycloak_db -export POSTGRES_USER=keycloak_db_user -export POSTGRES_PASSWORD=keycload_db_password_4_now -export KEYCLOAK_ADMIN=admin -export KEYCLOAK_ADMIN_PASSWORD=not4u2no \ No newline at end of file +ORCHESTRATOR_URL=https://hexa-orchestrator:8885 + +HEXA_CA_CERT=/Users/pjdhunt/git/policy-orchestrator/demo/.certs/ca-cert.pem +HEXA_JWT_AUTH_ENABLE=true +HEXA_JWT_REALM=Hexa-Orchestrator-Realm +HEXA_OAUTH_CLIENT_ID=hexaclient +HEXA_OAUTH_CLIENT_SECRET=uuXVzfbqH635Ob0oTON1uboONUqasmTt +HEXA_OAUTH_TOKEN_ENDPOINT=http://127.0.0.1:8080/realms/Hexa-Orchestrator-Realm/protocol/openid-connect/token +HEXA_OIDC_CLIENT_ID=hexaclient +HEXA_OIDC_CLIENT_SECRET=uuXVzfbqH635Ob0oTON1uboONUqasmTt +HEXA_OIDC_ENABLED=true +HEXA_OIDC_PROVIDER_URL=http://localhost:8080/realms/Hexa-Orchestrator-Realm +OPA_SERVER_URL=http://opa-agent:8887/v1/data/authz/allow +ORCHESTRATOR_URL=https://hexa-orchestrator:8885 +ORCHESTRATOR_HOSTPORT=0.0.0.0:8885 +HEXA_DEMO_URL=http://0.0.0.0:8886 +HEXA_DEMO_CONFIG_URL=http://0.0.0.0:8889 +ORCHESTRATOR_CONFIG_FILE=./deployments/hexaOrchestrator/config/config.json +POSTGRES_DB=keycloak_db +POSTGRES_USER=keycloak_db_user +POSTGRES_PASSWORD=keycload_db_password_4_now +KEYCLOAK_ADMIN=admin +KEYCLOAK_ADMIN_PASSWORD=not4u2no \ No newline at end of file diff --git a/demo/cmd/admin/admin.go b/demo/cmd/admin/admin.go index 9f012d42..3b3fd92d 100644 --- a/demo/cmd/admin/admin.go +++ b/demo/cmd/admin/admin.go @@ -6,6 +6,8 @@ import ( "net/http" "os" + "github.com/hexa-org/policy-mapper/pkg/keysupport" + "github.com/hexa-org/policy-mapper/pkg/sessionSupport" "github.com/hexa-org/policy-orchestrator/demo/pkg/hexaConstants" log "golang.org/x/exp/slog" @@ -17,7 +19,10 @@ import ( func App(addr string, orchestratorUrl string) *http.Server { client := admin.NewOrchestratorClient(nil, orchestratorUrl) - handlers := admin.LoadHandlers(orchestratorUrl, client) + + sessionHandler := sessionSupport.NewSessionManager() + + handlers := admin.LoadHandlers(orchestratorUrl, client, sessionHandler) return websupport.Create(addr, handlers, websupport.Options{}) } @@ -31,7 +36,19 @@ func newApp(addr string) (*http.Server, net.Listener) { orchestratorUrl := os.Getenv("ORCHESTRATOR_URL") listener, _ := net.Listen("tcp", addr) - return App(listener.Addr().String(), orchestratorUrl), listener + server := App(listener.Addr().String(), orchestratorUrl) + + if websupport.IsTlsEnabled() { + keyConfig := keysupport.GetKeyConfig() + err := keyConfig.InitializeKeys() + if err != nil { + log.Error("Error initializing keys: " + err.Error()) + panic(err) + } + + websupport.WithTransportLayerSecurity(keyConfig.ServerCertPath, keyConfig.ServerKeyPath, server) + } + return server, listener } func main() { diff --git a/demo/docker-compose.yml b/demo/docker-compose.yml index e8d3be05..26272a3f 100644 --- a/demo/docker-compose.yml +++ b/demo/docker-compose.yml @@ -15,7 +15,7 @@ services: HEXA_CERT_DIRECTORY: "/home/certs" HEXA_SERVER_CERT: "/home/certs/server-hexaorchestrator-cert.pem" HEXA_SERVER_KEY_PATH: "/home/certs/server-hexaorchestrator-key.pem" - HEXA_SERVER_DNS_NAME: "hexa-orchestrator" + HEXA_SERVER_DNS_NAME: "hexa-orchestrator,localhost" HEXA_JWT_REALM: Hexa-Orchestrator-Realm HEXA_TOKEN_JWKSURL: http://keycloak:8080/realms/Hexa-Orchestrator-Realm/protocol/openid-connect/certs HEXA_JWT_AUTH_ENABLE: true @@ -41,7 +41,13 @@ services: - hexa_network environment: ORCHESTRATOR_URL: https://hexa-orchestrator:8885 + # HEXA_CA_CERT used to install the self-signed CA trust root to call Orchestrator service HEXA_CA_CERT: "/home/certs/ca-cert.pem" + HEXA_TLS_ENABLED: false + HEXA_CERT_DIRECTORY: "/home/certs" + HEXA_SERVER_CERT: "/home/certs/server-hexa-admin-cert.pem" + HEXA_SERVER_KEY_PATH: "/home/certs/server-hexa-admin-key.pem" + HEXA_SERVER_DNS_NAME: "admin.hexa.org,localhost" HEXA_JWT_REALM: Hexa-Orchestrator-Realm HEXA_JWT_AUTH_ENABLE: true HEXA_OAUTH_CLIENT_ID: hexaclient @@ -59,6 +65,7 @@ services: hexa-industry-demo-app: image: independentid/hexaopa:latest container_name: hexa-demo + hostname: demo.hexa.org ports: - "8886:8886" command: /app/hexaIndustriesDemo @@ -69,8 +76,22 @@ services: environment: PORT: 8886 OPA_SERVER_URL: https://hexa-opa-server:8887/v1/data/hexaPolicy - HEXAOPA_DETAIL: "notes&pretty" + # HEXAOPA_DETAIL enables debug responses in console notes, fails, full, debug + HEXAOPA_DETAIL: "notes" + # HEXA_CA_CERT is used to trust self-signed TLS keys for hexa-opa-sidecar (OPA_SERVER_URL) HEXA_CA_CERT: "/home/certs/ca-cert.pem" + HEXA_CERT_DIRECTORY: "/home/certs" + HEXA_OIDC_ENABLED: true + HEXA_OIDC_CLIENT_ID: hexaclient + HEXA_OIDC_CLIENT_SECRET: "uuXVzfbqH635Ob0oTON1uboONUqasmTt" + HEXA_OIDC_PROVIDER_URL: "http://keycloak:8080/realms/Hexa-Orchestrator-Realm" + # If TLS enabled, OIDC redirect must be changed to https + HEXA_OIDC_REDIRECT_URL: "http://demo.hexa.org:8886/redirect" + HEXA_TLS_ENABLED: false + # Following only used when HEXA_TLS_ENABLED=true and auto generate keys enabled (default) + HEXA_SERVER_CERT: "/home/certs/server-hexademo-cert.pem" + HEXA_SERVER_KEY_PATH: "/home/certs/server-hexademo-key.pem" + HEXA_SERVER_DNS_NAME: "demo.hexa.org,localhost" volumes: - "./.certs:/home/certs:ro" diff --git a/demo/internal/admin/admin.go b/demo/internal/admin/admin.go index 860c6160..636295f2 100644 --- a/demo/internal/admin/admin.go +++ b/demo/internal/admin/admin.go @@ -7,6 +7,9 @@ import ( "github.com/gorilla/mux" "github.com/hexa-org/policy-mapper/pkg/hexapolicy" + "github.com/hexa-org/policy-mapper/pkg/oidcSupport" + "github.com/hexa-org/policy-mapper/pkg/sessionSupport" + log "golang.org/x/exp/slog" ) //go:embed resources @@ -29,29 +32,42 @@ func IndexHandler(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, "/integrations", http.StatusPermanentRedirect) } -func LoadHandlers(orchestratorUrl string, client Client) func(router *mux.Router) { - apps := NewApplicationsHandler(orchestratorUrl, client) - integrations := NewIntegrationsHandler(orchestratorUrl, client) - orchestration := NewOrchestrationHandler(orchestratorUrl, client) +func LoadHandlers(orchestratorUrl string, client Client, sessionHandler sessionSupport.SessionManager) func(router *mux.Router) { + + oidcHandler, err := oidcSupport.NewOidcClientHandler(sessionHandler, &resources) + apps := NewApplicationsHandler(sessionHandler, orchestratorUrl, client) + + integrations := NewIntegrationsHandler(orchestratorUrl, client, sessionHandler) + orchestration := NewOrchestrationHandler(orchestratorUrl, client, sessionHandler) status := NewStatusHandler(orchestratorUrl, client) return func(router *mux.Router) { - router.HandleFunc("/", IndexHandler).Methods("GET") - router.HandleFunc("/integrations", integrations.List).Methods("GET") - router.HandleFunc("/integrations/new", integrations.New).Methods("GET").Queries("provider", "{provider}") - router.HandleFunc("/integrations", integrations.CreateIntegration).Methods("POST") - router.HandleFunc("/integrations/{id}", integrations.Delete).Methods("POST") - router.HandleFunc("/applications", apps.List).Methods("GET") - router.HandleFunc("/applications/{id}", apps.Show).Methods("GET") - router.HandleFunc("/applications/{id}/policies", apps.Policies).Methods("GET") - router.HandleFunc("/applications/{id}/edit", apps.Edit).Methods("GET") - router.HandleFunc("/applications/{id}", apps.Update).Methods("POST") - router.HandleFunc("/orchestration/new", orchestration.New).Methods("GET") - router.HandleFunc("/orchestration", orchestration.Update).Methods("POST") - router.HandleFunc("/status", status.StatusHandler).Methods("GET") + + oidcHandler.InitHandlers(router) + if err != nil { + log.Error(err.Error()) + log.Warn("OIDC Login is disabled") + } + if !oidcHandler.Enabled { + router.HandleFunc("/", IndexHandler) + } + + router.HandleFunc("/integrations", oidcHandler.HandleSessionScope(integrations.List, []string{"integration"})).Methods("GET") + router.HandleFunc("/integrations/new", oidcHandler.HandleSessionScope(integrations.New, []string{"integration"})).Methods("GET").Queries("provider", "{provider}") + router.HandleFunc("/integrations", oidcHandler.HandleSessionScope(integrations.CreateIntegration, []string{"integration"})).Methods("POST") + router.HandleFunc("/integrations/{id}", oidcHandler.HandleSessionScope(integrations.Delete, []string{"integration"})).Methods("POST") + router.HandleFunc("/applications", oidcHandler.HandleSessionScope(apps.List, []string{"integration"})).Methods("GET") + router.HandleFunc("/applications/{id}", oidcHandler.HandleSessionScope(apps.Show, []string{"integration"})).Methods("GET") + router.HandleFunc("/applications/{id}/policies", oidcHandler.HandleSessionScope(apps.Policies, []string{"integration"})).Methods("GET") + router.HandleFunc("/applications/{id}/edit", oidcHandler.HandleSessionScope(apps.Edit, []string{"integration"})).Methods("GET") + router.HandleFunc("/applications/{id}", oidcHandler.HandleSessionScope(apps.Update, []string{"integration"})).Methods("POST") + router.HandleFunc("/orchestration/new", oidcHandler.HandleSessionScope(orchestration.New, []string{"integration"})).Methods("GET") + router.HandleFunc("/orchestration", oidcHandler.HandleSessionScope(orchestration.Update, []string{"integration"})).Methods("POST") + router.HandleFunc("/status", oidcHandler.HandleSessionScope(status.StatusHandler, []string{"integration"})).Methods("GET") staticFs, _ := fs.Sub(resources, "resources/static") fileServer := http.FileServer(http.FS(staticFs)) router.PathPrefix("/").Handler(http.StripPrefix("/", fileServer)) } + } diff --git a/demo/internal/admin/admin_test.go b/demo/internal/admin/admin_test.go index 997d3bfb..30faae3b 100644 --- a/demo/internal/admin/admin_test.go +++ b/demo/internal/admin/admin_test.go @@ -6,6 +6,7 @@ import ( "net/http" "testing" + "github.com/hexa-org/policy-mapper/pkg/sessionSupport" "github.com/hexa-org/policy-orchestrator/demo/internal/admin" "github.com/hexa-org/policy-orchestrator/demo/internal/admin/test" @@ -15,8 +16,9 @@ import ( ) func TestAdminHandlers(t *testing.T) { + sessionHandler := sessionSupport.NewSessionManager() listener, _ := net.Listen("tcp", "localhost:0") - handlers := admin.LoadHandlers("localhost:8885", new(admin_test.MockClient)) + handlers := admin.LoadHandlers("localhost:8885", new(admin_test.MockClient), sessionHandler) server := websupport.Create(listener.Addr().String(), handlers, websupport.Options{}) go websupport.Start(server, listener) healthsupport.WaitForHealthy(server) diff --git a/demo/internal/admin/applications.go b/demo/internal/admin/applications.go index 6ed52b9b..35db58d9 100644 --- a/demo/internal/admin/applications.go +++ b/demo/internal/admin/applications.go @@ -8,6 +8,7 @@ import ( "net/http" "github.com/gorilla/mux" + "github.com/hexa-org/policy-mapper/pkg/sessionSupport" "github.com/hexa-org/policy-mapper/pkg/websupport" ) @@ -32,10 +33,11 @@ type ApplicationsHandler interface { type appsHandler struct { orchestratorUrl string client Client + session sessionSupport.SessionManager } -func NewApplicationsHandler(orchestratorUrl string, client Client) ApplicationsHandler { - return appsHandler{orchestratorUrl, client} +func NewApplicationsHandler(sessionHandler sessionSupport.SessionManager, orchestratorUrl string, client Client) ApplicationsHandler { + return appsHandler{orchestratorUrl, client, sessionHandler} } func (p appsHandler) List(w http.ResponseWriter, r *http.Request) { @@ -51,7 +53,11 @@ func (p appsHandler) List(w http.ResponseWriter, r *http.Request) { log.Println(clientErr) return } - model := websupport.Model{Map: map[string]interface{}{"resource": "applications", "applications": foundApplications}} + sessionInfo, err := p.session.Session(r) + if err != nil { + sessionInfo = &sessionSupport.SessionInfo{} + } + model := websupport.Model{Map: map[string]interface{}{"resource": "applications", "applications": foundApplications, "session": sessionInfo}} _ = websupport.ModelAndView(w, &resources, "applications", model) w.Header() } @@ -79,7 +85,11 @@ func (p appsHandler) Show(w http.ResponseWriter, r *http.Request) { var buffer bytes.Buffer _ = json.Indent(&buffer, []byte(rawJson), "", " ") resourceLink := fmt.Sprintf("/applications/%v", identifier) - model := websupport.Model{Map: map[string]interface{}{"resource": "applications", "resource_link": resourceLink, "application": foundApplication, "policies": foundPolicies, "rawJson": buffer.String()}} + sessionInfo, err := p.session.Session(r) + if err != nil { + sessionInfo = &sessionSupport.SessionInfo{} + } + model := websupport.Model{Map: map[string]interface{}{"resource": "applications", "resource_link": resourceLink, "application": foundApplication, "policies": foundPolicies, "rawJson": buffer.String(), "session": sessionInfo}} _ = websupport.ModelAndView(w, &resources, "applications_show", model) } @@ -94,9 +104,14 @@ func (p appsHandler) Edit(w http.ResponseWriter, r *http.Request) { return } + sessionInfo, err := p.session.Session(r) + if err != nil { + sessionInfo = &sessionSupport.SessionInfo{} + } foundPolicies, rawJson, policiesError := p.client.GetPolicies(identifier) if policiesError != nil { - model := websupport.Model{Map: map[string]interface{}{"resource": "applications", "application": foundApplication, "message": policiesError.Error()}} + + model := websupport.Model{Map: map[string]interface{}{"resource": "applications", "application": foundApplication, "message": policiesError.Error(), "session": sessionInfo}} _ = websupport.ModelAndView(w, &resources, "applications_edit", model) log.Println(policiesError) return @@ -104,7 +119,7 @@ func (p appsHandler) Edit(w http.ResponseWriter, r *http.Request) { var buffer bytes.Buffer _ = json.Indent(&buffer, []byte(rawJson), "", " ") - model := websupport.Model{Map: map[string]interface{}{"resource": "applications", "application": foundApplication, "policies": foundPolicies, "rawJson": buffer.String()}} + model := websupport.Model{Map: map[string]interface{}{"resource": "applications", "application": foundApplication, "policies": foundPolicies, "rawJson": buffer.String(), "session": sessionInfo}} _ = websupport.ModelAndView(w, &resources, "applications_edit", model) } diff --git a/demo/internal/admin/applications_test.go b/demo/internal/admin/applications_test.go index a8b86100..a081db62 100644 --- a/demo/internal/admin/applications_test.go +++ b/demo/internal/admin/applications_test.go @@ -6,9 +6,12 @@ import ( "io" "net" "net/http" + "os" "testing" "github.com/hexa-org/policy-mapper/pkg/hexapolicy" + "github.com/hexa-org/policy-mapper/pkg/oidcSupport" + "github.com/hexa-org/policy-mapper/pkg/sessionSupport" "github.com/hexa-org/policy-orchestrator/demo/internal/admin" "github.com/hexa-org/policy-orchestrator/demo/internal/admin/test" @@ -31,9 +34,11 @@ func TestApplications(t *testing.T) { func (suite *ApplicationsSuite) SetupTest() { listener, _ := net.Listen("tcp", "localhost:0") suite.client = &admin_test.MockClient{Url: "http://noop"} + _ = os.Setenv(oidcSupport.EnvOidcEnabled, "false") + sessionHandler := sessionSupport.NewSessionManager() suite.server = websupport.Create( listener.Addr().String(), - admin.LoadHandlers("http://noop", suite.client), + admin.LoadHandlers("http://noop", suite.client, sessionHandler), websupport.Options{}) go websupport.Start(suite.server, listener) healthsupport.WaitForHealthy(suite.server) diff --git a/demo/internal/admin/integrations.go b/demo/internal/admin/integrations.go index f525c6c7..a7b58396 100644 --- a/demo/internal/admin/integrations.go +++ b/demo/internal/admin/integrations.go @@ -8,9 +8,9 @@ import ( "strings" "github.com/gorilla/mux" - "github.com/hexa-org/policy-mapper/sdk" - + "github.com/hexa-org/policy-mapper/pkg/sessionSupport" "github.com/hexa-org/policy-mapper/pkg/websupport" + "github.com/hexa-org/policy-mapper/sdk" ) type IntegrationProviderInterface interface { @@ -36,17 +36,19 @@ type integrationsHandler struct { orchestratorUrl string client Client providerStructs []IntegrationProviderInterface + session sessionSupport.SessionManager } -func NewIntegrationsHandler(orchestratorUrl string, client Client) IntegrationHandler { +func NewIntegrationsHandler(orchestratorUrl string, client Client, sessionHandler sessionSupport.SessionManager) IntegrationHandler { return integrationsHandler{ orchestratorUrl, client, []IntegrationProviderInterface{googleProvider{}, azureProvider{}, amazonProvider{}, awsApiGatewayProvider{}, avpProvider{}, opaProvider{}}, + sessionHandler, } } -func (i integrationsHandler) List(w http.ResponseWriter, _ *http.Request) { +func (i integrationsHandler) List(w http.ResponseWriter, r *http.Request) { integrations, err := i.client.Integrations() if err != nil { model := websupport.Model{Map: map[string]interface{}{"resource": "integrations", "message": "Unable to contact orchestrator."}} @@ -63,13 +65,21 @@ func (i integrationsHandler) List(w http.ResponseWriter, _ *http.Request) { } return false }) - model := websupport.Model{Map: map[string]interface{}{"resource": "integrations", "integrations": integrations}} + sessionInfo, err := i.session.Session(r) + if err != nil { + sessionInfo = &sessionSupport.SessionInfo{} + } + model := websupport.Model{Map: map[string]interface{}{"resource": "integrations", "integrations": integrations, "session": sessionInfo}} _ = websupport.ModelAndView(w, &resources, "integrations", model) } func (i integrationsHandler) New(w http.ResponseWriter, r *http.Request) { provider := r.URL.Query().Get("provider") - model := websupport.Model{Map: map[string]interface{}{"resource": "integrations", "provider": provider}} + sessionInfo, err := i.session.Session(r) + if err != nil { + sessionInfo = &sessionSupport.SessionInfo{} + } + model := websupport.Model{Map: map[string]interface{}{"resource": "integrations", "provider": provider, "session": sessionInfo}} integrationView := i.knownIntegrationViews(provider) _ = websupport.ModelAndView(w, &resources, integrationView, model) } @@ -89,7 +99,11 @@ func (i integrationsHandler) CreateIntegration(w http.ResponseWriter, r *http.Re file, _, err := r.FormFile("key") if err != nil { log.Printf("Missing key file %s.\n", err.Error()) - model := websupport.Model{Map: map[string]interface{}{"resource": "integrations", "provider": provider, "message": "Missing key file."}} + sessionInfo, err := i.session.Session(r) + if err != nil { + sessionInfo = &sessionSupport.SessionInfo{} + } + model := websupport.Model{Map: map[string]interface{}{"resource": "integrations", "provider": provider, "message": "Missing key file.", "session": sessionInfo}} _ = websupport.ModelAndView(w, &resources, integrationView, model) return } @@ -118,7 +132,11 @@ func (i integrationsHandler) CreateIntegration(w http.ResponseWriter, r *http.Re err = i.client.CreateIntegration(name, provider, key) if err != nil { - model := websupport.Model{Map: map[string]interface{}{"resource": "integrations", "provider": provider, "message": "Unable to communicate with orchestrator."}} + sessionInfo, err := i.session.Session(r) + if err != nil { + sessionInfo = &sessionSupport.SessionInfo{} + } + model := websupport.Model{Map: map[string]interface{}{"resource": "integrations", "provider": provider, "message": "Unable to communicate with orchestrator.", "session": sessionInfo}} _ = websupport.ModelAndView(w, &resources, integrationView, model) return } @@ -135,6 +153,7 @@ func (i integrationsHandler) Delete(w http.ResponseWriter, r *http.Request) { } func (i integrationsHandler) viewWithMessage(w http.ResponseWriter, provider string, message string, integrationView string) { + model := websupport.Model{Map: map[string]interface{}{"resource": "integrations", "provider": provider, "message": message}} _ = websupport.ModelAndView(w, &resources, integrationView, model) } diff --git a/demo/internal/admin/integrations_test.go b/demo/internal/admin/integrations_test.go index 0b40ed76..764e8816 100644 --- a/demo/internal/admin/integrations_test.go +++ b/demo/internal/admin/integrations_test.go @@ -12,6 +12,7 @@ import ( "net/url" "testing" + "github.com/hexa-org/policy-mapper/pkg/sessionSupport" "github.com/hexa-org/policy-orchestrator/demo/internal/admin" "github.com/hexa-org/policy-orchestrator/demo/internal/admin/test" @@ -34,9 +35,10 @@ func TestIntegrations(t *testing.T) { func (suite *IntegrationsSuite) SetupTest() { listener, _ := net.Listen("tcp", "localhost:0") suite.client = &admin_test.MockClient{Url: "http://noop"} + sessionHandler := sessionSupport.NewSessionManager() suite.server = websupport.Create( listener.Addr().String(), - admin.LoadHandlers("http://noop", suite.client), + admin.LoadHandlers("http://noop", suite.client, sessionHandler), websupport.Options{}) go websupport.Start(suite.server, listener) healthsupport.WaitForHealthy(suite.server) diff --git a/demo/internal/admin/orchestration.go b/demo/internal/admin/orchestration.go index cda31894..04bf72f6 100644 --- a/demo/internal/admin/orchestration.go +++ b/demo/internal/admin/orchestration.go @@ -4,6 +4,7 @@ import ( "log" "net/http" + "github.com/hexa-org/policy-mapper/pkg/sessionSupport" "github.com/hexa-org/policy-mapper/pkg/websupport" ) @@ -15,16 +16,22 @@ type OrchestrationHandler interface { type orchestrationHandler struct { orchestratorUrl string client Client + session sessionSupport.SessionManager } -func NewOrchestrationHandler(orchestratorUrl string, client Client) OrchestrationHandler { - return orchestrationHandler{orchestratorUrl, client} +func NewOrchestrationHandler(orchestratorUrl string, client Client, sessionHandler sessionSupport.SessionManager) OrchestrationHandler { + return orchestrationHandler{orchestratorUrl, client, sessionHandler} } -func (p orchestrationHandler) New(w http.ResponseWriter, _ *http.Request) { +func (p orchestrationHandler) New(w http.ResponseWriter, r *http.Request) { foundApplications, clientErr := p.client.Applications(false) + sessionInfo, err := p.session.Session(r) + if err != nil { + sessionInfo = &sessionSupport.SessionInfo{} + } if clientErr != nil { - model := websupport.Model{Map: map[string]interface{}{"resource": "orchestration", "message": clientErr.Error()}} + + model := websupport.Model{Map: map[string]interface{}{"resource": "orchestration", "message": clientErr.Error(), "session": sessionInfo}} _ = websupport.ModelAndView(w, &resources, "orchestration_new", model) log.Println(clientErr) return @@ -39,7 +46,7 @@ func (p orchestrationHandler) New(w http.ResponseWriter, _ *http.Request) { } }*/ - model := websupport.Model{Map: map[string]interface{}{"resource": "orchestration", "applications": foundApplications}} + model := websupport.Model{Map: map[string]interface{}{"resource": "orchestration", "applications": foundApplications, "session": sessionInfo}} _ = websupport.ModelAndView(w, &resources, "orchestration_new", model) } diff --git a/demo/internal/admin/orchestration_test.go b/demo/internal/admin/orchestration_test.go index c849cf4a..785bc270 100644 --- a/demo/internal/admin/orchestration_test.go +++ b/demo/internal/admin/orchestration_test.go @@ -8,6 +8,7 @@ import ( "net/http" "testing" + "github.com/hexa-org/policy-mapper/pkg/sessionSupport" "github.com/hexa-org/policy-orchestrator/demo/internal/admin" "github.com/hexa-org/policy-orchestrator/demo/internal/admin/test" @@ -30,9 +31,10 @@ func TestOrchestration(t *testing.T) { func (suite *OrchestrationSuite) SetupTest() { listener, _ := net.Listen("tcp", "localhost:0") suite.client = &admin_test.MockClient{Url: "http://noop"} + sessionHandler := sessionSupport.NewSessionManager() suite.server = websupport.Create( listener.Addr().String(), - admin.LoadHandlers("http://noop", suite.client), + admin.LoadHandlers("http://noop", suite.client, sessionHandler), websupport.Options{}) go websupport.Start(suite.server, listener) healthsupport.WaitForHealthy(suite.server) diff --git a/demo/internal/admin/orchestrator_client_test.go b/demo/internal/admin/orchestrator_client_test.go index 2813c7cf..8c313c30 100644 --- a/demo/internal/admin/orchestrator_client_test.go +++ b/demo/internal/admin/orchestrator_client_test.go @@ -13,8 +13,8 @@ import ( "testing" "github.com/hexa-org/policy-mapper/pkg/hexapolicy" + "github.com/hexa-org/policy-mapper/pkg/mockOidcSupport" "github.com/hexa-org/policy-mapper/pkg/oauth2support" - "github.com/hexa-org/policy-mapper/pkg/oidctestsupport" "github.com/hexa-org/policy-orchestrator/demo/internal/admin" "golang.org/x/oauth2" @@ -43,7 +43,7 @@ func (m *MockClient) Get(_ string) (resp *http.Response, err error) { func TestOrchestratorJwtClient(t *testing.T) { log.Println("Starting Mock OAuth Server") cid := "testClientId" - mockAuth := oidctestsupport.NewMockAuthServer(cid, "secret", map[string]interface{}{}) + mockAuth := mockOidcSupport.NewMockAuthServer(cid, "secret", map[string]interface{}{}) defer mockAuth.Server.Close() mockerAddr := mockAuth.Server.URL mockUrlJwks, _ := url.JoinPath(mockerAddr, "/jwks") diff --git a/demo/internal/admin/resources/static/styles/app.css b/demo/internal/admin/resources/static/styles/app.css index 284eda70..ce21ffed 100644 --- a/demo/internal/admin/resources/static/styles/app.css +++ b/demo/internal/admin/resources/static/styles/app.css @@ -82,6 +82,22 @@ form p { vertical-align: top; } +.login { + border-radius: 10px; + padding: 1rem; + + background: var(--gray); + color: white; + cursor: pointer; + border: solid; + font-size: inherit; + + display: inline-block; + line-height: 2rem; + horiz-align: center; + vertical-align: middle; +} + .button.secondary { color: var(--medium-gray); background-color: var(--light-gray); diff --git a/demo/internal/admin/resources/templates/login.gohtml b/demo/internal/admin/resources/templates/login.gohtml new file mode 100644 index 00000000..2f103fe1 --- /dev/null +++ b/demo/internal/admin/resources/templates/login.gohtml @@ -0,0 +1,8 @@ +{{- template "base" .}} +{{- define "main"}} + <div class="content"> + + <a href="/login" class="login">Login using OIDC</a> + + </div> +{{- end}} diff --git a/demo/internal/admin/resources/templates/template.gohtml b/demo/internal/admin/resources/templates/template.gohtml index 5df5d9dd..3c4cdde4 100644 --- a/demo/internal/admin/resources/templates/template.gohtml +++ b/demo/internal/admin/resources/templates/template.gohtml @@ -1,6 +1,7 @@ {{- define "base"}} {{- $resource := index .Map "resource"}} {{- $resource_link := index .Map "resource_link"}} + {{- $userInfo := index .Map "session"}} <!doctype html> <html lang="en"> <head> @@ -17,7 +18,11 @@ <nav class="top-nav top-bar"> <h1 class="hexa-title">Policy Administrator</h1> - <div class="gray">Log out</div> + <div class="gray"> + {{- if (ne $userInfo.Email "") }} + {{ $userInfo.Email }} + {{ end }} + </div> </nav> <header class="top-bar"> @@ -53,6 +58,7 @@ </header> <main> <div class="side-nav"> + {{- if (ne $resource "login") }} <ul> <li class="no-hover"> <h2>Administrator</h2> @@ -85,9 +91,10 @@ </ul> <ul> <li> - Log out + <a href="/logout">Log out</a> </li> </ul> + {{end}} </div> <div class="content"> diff --git a/demo/internal/orchestrator/applications_handler_test.go b/demo/internal/orchestrator/applications_handler_test.go index e7d9ecad..d46b1248 100644 --- a/demo/internal/orchestrator/applications_handler_test.go +++ b/demo/internal/orchestrator/applications_handler_test.go @@ -17,8 +17,8 @@ import ( "github.com/hexa-org/policy-mapper/api/policyprovider" "github.com/hexa-org/policy-mapper/pkg/healthsupport" "github.com/hexa-org/policy-mapper/pkg/hexapolicy" + "github.com/hexa-org/policy-mapper/pkg/mockOidcSupport" "github.com/hexa-org/policy-mapper/pkg/oauth2support" - "github.com/hexa-org/policy-mapper/pkg/oidctestsupport" "github.com/hexa-org/policy-mapper/pkg/websupport" "github.com/hexa-org/policy-mapper/sdk" "github.com/hexa-org/policy-orchestrator/demo/internal/orchestrator" @@ -36,7 +36,7 @@ type applicationsHandlerData struct { key string providers map[string]policyprovider.Provider applicationTestId string - MockOauth *oidctestsupport.MockAuthServer + MockOauth *mockOidcSupport.MockAuthServer oauthHttpClient *http.Client } @@ -45,7 +45,7 @@ func (data *applicationsHandlerData) SetUp() { tempDir, _ := os.MkdirTemp("", "hexa-orchestrator-*") data.testDir = tempDir // The Mock Authorization Server is needed to issue tokens, and provide a JWKS endpoint for validation - data.MockOauth = oidctestsupport.NewMockAuthServer("clientId", "secret", map[string]interface{}{}) + data.MockOauth = mockOidcSupport.NewMockAuthServer("clientId", "secret", map[string]interface{}{}) mockUrlJwks, _ := url.JoinPath(data.MockOauth.Server.URL, "/jwks") tokenUrl, _ := url.JoinPath(data.MockOauth.Server.URL, "/token") diff --git a/demo/internal/orchestrator/integrations_handler_test.go b/demo/internal/orchestrator/integrations_handler_test.go index 757e42fc..52c49fb5 100644 --- a/demo/internal/orchestrator/integrations_handler_test.go +++ b/demo/internal/orchestrator/integrations_handler_test.go @@ -14,8 +14,8 @@ import ( "testing" "github.com/hexa-org/policy-mapper/api/policyprovider" + "github.com/hexa-org/policy-mapper/pkg/mockOidcSupport" "github.com/hexa-org/policy-mapper/pkg/oauth2support" - "github.com/hexa-org/policy-mapper/pkg/oidctestsupport" "github.com/hexa-org/policy-mapper/sdk" "github.com/hexa-org/policy-orchestrator/demo/internal/orchestrator" orchestratortest "github.com/hexa-org/policy-orchestrator/demo/internal/orchestrator/test" @@ -34,7 +34,7 @@ type HandlerSuite struct { testDir string Data *dataConfigGateway.ConfigData gateway dataConfigGateway.IntegrationsDataGateway - MockOauth *oidctestsupport.MockAuthServer + MockOauth *mockOidcSupport.MockAuthServer oauthHttpClient *http.Client } @@ -42,7 +42,7 @@ func TestIntegrationsHandler(t *testing.T) { var err error s := HandlerSuite{} // The Mock Authorization Server is needed to issue tokens, and provide a JWKS endpoint for validation - s.MockOauth = oidctestsupport.NewMockAuthServer("clientId", "secret", map[string]interface{}{}) + s.MockOauth = mockOidcSupport.NewMockAuthServer("clientId", "secret", map[string]interface{}{}) mockUrlJwks, _ := url.JoinPath(s.MockOauth.Server.URL, "/jwks") // Set Env for Jwt Token Validation by Orchestrator handlers _ = os.Setenv(oauth2support.EnvOAuthJwksUrl, mockUrlJwks) diff --git a/demo/internal/orchestrator/orchestration_handler_test.go b/demo/internal/orchestrator/orchestration_handler_test.go index c96a592e..7a2966b1 100644 --- a/demo/internal/orchestrator/orchestration_handler_test.go +++ b/demo/internal/orchestrator/orchestration_handler_test.go @@ -14,8 +14,8 @@ import ( "testing" "github.com/hexa-org/policy-mapper/api/policyprovider" + "github.com/hexa-org/policy-mapper/pkg/mockOidcSupport" "github.com/hexa-org/policy-mapper/pkg/oauth2support" - "github.com/hexa-org/policy-mapper/pkg/oidctestsupport" "github.com/hexa-org/policy-mapper/sdk" "github.com/hexa-org/policy-orchestrator/demo/internal/orchestrator" "github.com/hexa-org/policy-orchestrator/demo/internal/orchestrator/test" @@ -40,7 +40,7 @@ type orchestrationHandlerData struct { Data *dataConfigGateway.ConfigData appGateway dataConfigGateway.ApplicationsDataGateway - MockOauth *oidctestsupport.MockAuthServer + MockOauth *mockOidcSupport.MockAuthServer oauthHttpClient *http.Client } @@ -59,7 +59,7 @@ func (data *orchestrationHandlerData) SetUp() { `) */ - data.MockOauth = oidctestsupport.NewMockAuthServer("clientId", "secret", map[string]interface{}{}) + data.MockOauth = mockOidcSupport.NewMockAuthServer("clientId", "secret", map[string]interface{}{}) mockUrlJwks, _ := url.JoinPath(data.MockOauth.Server.URL, "/jwks") // Set Env for Jwt Token Validation by Orchestrator handlers _ = os.Setenv(oauth2support.EnvOAuthJwksUrl, mockUrlJwks) diff --git a/demo/pkg/hexaConstants/hexaConstants.go b/demo/pkg/hexaConstants/hexaConstants.go index 65a8c9e4..e4cf24ee 100644 --- a/demo/pkg/hexaConstants/hexaConstants.go +++ b/demo/pkg/hexaConstants/hexaConstants.go @@ -1,5 +1,5 @@ package hexaConstants const ( - HexaOrchestratorVersion string = "v0.6.0" + HexaOrchestratorVersion string = "v0.6.15" )