Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BED-4766: API Endpoint to List OIDC Providers #896

Merged
merged 31 commits into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
97eb109
BED-4851 Updated CreateOIDCProvider endpoint and relevant database in…
mvlipka Sep 30, 2024
e7111dd
BED-4851 updates to conform to new design
mvlipka Oct 1, 2024
2a22dc6
BED-4851 cleanup import
mvlipka Oct 1, 2024
5028c18
BED-4851 added integration test for TestBloodhoundDB_CreateSSOProvide…
mvlipka Oct 2, 2024
686a359
BED-4851 removed name from oidc_providers
mvlipka Oct 2, 2024
6a67c61
BED-4851 updated tests with removed name field
mvlipka Oct 2, 2024
4c818e7
BED-4851 idempotent saml_providers constraint
mvlipka Oct 2, 2024
0723780
BED-4851 moved responsibility of slug creation to the db layer. Prope…
mvlipka Oct 3, 2024
022d2a6
Merge main
mvlipka Oct 3, 2024
6877860
generate
mvlipka Oct 3, 2024
704c330
removed test I was playing with and accidentally committed, oops. Add…
mvlipka Oct 3, 2024
e55f5e0
fix returning error from CreateSSOPRovider
mvlipka Oct 3, 2024
1cf416d
added test for invalid SessionAuthProvider
mvlipka Oct 3, 2024
0be0354
fixed test, better naming on sso provider types
mvlipka Oct 3, 2024
d1e0ce3
list without sortinga and filtering complete
iustinum Oct 3, 2024
5b4edcc
removed no longer used SetupTransaction
mvlipka Oct 4, 2024
fbdae9b
unit and integration test passed
iustinum Oct 4, 2024
b0e7b4f
adjust list endpoint after removing name in oidc provider
iustinum Oct 4, 2024
aa64447
merge branch bed-4766-v2
iustinum Oct 4, 2024
5d5c5b5
cleanup for pr
iustinum Oct 4, 2024
328d953
integrate new sso auth workflow to outdated test case
iustinum Oct 7, 2024
c27cfa7
resolve merge conflict after create api merged to main
iustinum Oct 9, 2024
8ff6f1f
refactoring response struct after merged change on ssoProvider
iustinum Oct 9, 2024
fe8e280
db call optimization with sql joins
iustinum Oct 11, 2024
6438407
addresses duplicate ssoprovider creation in test function
iustinum Oct 11, 2024
1d024ab
Remove authmanageproviders permission from API route
iustinum Oct 11, 2024
9b86535
addresses nits
iustinum Oct 11, 2024
1ce012a
Update cmd/api/src/api/v2/analysisrequest.go
iustinum Oct 15, 2024
17bef89
Update cmd/api/src/api/v2/auth/sso.go
iustinum Oct 15, 2024
2aa3e41
Update cmd/api/src/api/v2/auth/sso.go
iustinum Oct 15, 2024
befd85a
Update cmd/api/src/api/v2/auth/sso.go
iustinum Oct 15, 2024
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
1 change: 1 addition & 0 deletions cmd/api/src/api/registration/v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ func registerV2Auth(cfg config.Configuration, db database.Database, permissions

// SSO
routerInst.POST("/api/v2/sso-providers/oidc", managementResource.CreateOIDCProvider).CheckFeatureFlag(db, appcfg.FeatureOIDCSupport).RequirePermissions(permissions.AuthManageProviders),
routerInst.GET("/api/v2/sso-providers", managementResource.ListAuthProviders).CheckFeatureFlag(db, appcfg.FeatureOIDCSupport),

// Permissions
routerInst.GET("/api/v2/permissions", managementResource.ListPermissions).RequirePermissions(permissions.AuthManageSelf),
Expand Down
5 changes: 3 additions & 2 deletions cmd/api/src/api/tools/analysis_schedule.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@ package tools

import (
"fmt"
"net/http"
"strings"

"github.com/specterops/bloodhound/src/api"
v2 "github.com/specterops/bloodhound/src/api/v2"
"github.com/specterops/bloodhound/src/database/types"
"github.com/specterops/bloodhound/src/model/appcfg"
"github.com/teambition/rrule-go"
"net/http"
"strings"
)

type ScheduledAnalysisConfiguration struct {
Expand Down
7 changes: 4 additions & 3 deletions cmd/api/src/api/tools/analysis_schedule_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,17 @@ import (
"bytes"
"context"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"

"github.com/golang/mock/gomock"
"github.com/gorilla/mux"
"github.com/specterops/bloodhound/headers"
"github.com/specterops/bloodhound/mediatypes"
"github.com/specterops/bloodhound/src/api/tools"
"github.com/specterops/bloodhound/src/ctx"
"github.com/stretchr/testify/require"
"net/http"
"net/http/httptest"
"testing"
)

func TestToolContainer_GetScheduledAnalysisConfiguration_Errors(t *testing.T) {
Expand Down
3 changes: 2 additions & 1 deletion cmd/api/src/api/v2/analysisrequest.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ package v2

import (
"database/sql"
"github.com/specterops/bloodhound/src/model/appcfg"
"net/http"

"github.com/specterops/bloodhound/src/model/appcfg"

iustinum marked this conversation as resolved.
Show resolved Hide resolved
"github.com/specterops/bloodhound/errors"
"github.com/specterops/bloodhound/log"
"github.com/specterops/bloodhound/src/api"
Expand Down
127 changes: 127 additions & 0 deletions cmd/api/src/api/v2/auth/sso.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
// Copyright 2024 Specter Ops, Inc.
//
// Licensed under the Apache License, Version 2.0
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0

package auth

import (
"net/http"
"strings"

"github.com/specterops/bloodhound/src/api"
"github.com/specterops/bloodhound/src/model"
"gorm.io/gorm/utils"
)

// AuthProvider represents a unified SSO provider (either OIDC or SAML)
type AuthProvider struct {
ID int32 `json:"id"`
Name string `json:"name"`
Type string `json:"type"`
Slug string `json:"slug"`
Details interface{} `json:"details"`
}

// ListAuthProviders lists all available SSO providers (SAML and OIDC) with sorting and filtering
func (s ManagementResource) ListAuthProviders(response http.ResponseWriter, request *http.Request) {
var (
ctx = request.Context()
queryParams = request.URL.Query()
sortByColumns = queryParams[api.QueryParameterSortBy]
order []string
queryFilters model.QueryParameterFilterMap
sqlFilter model.SQLFilter
ssoProviders []model.SSOProvider
providers []AuthProvider
err error
queryFilterParser = model.NewQueryParameterFilterParser()
)

for _, column := range sortByColumns {
var descending bool
if strings.HasPrefix(column, "-") {
descending = true
column = column[1:]
}

if !model.SSOProviderSortableFields(column) {
api.WriteErrorResponse(ctx, api.BuildErrorResponse(http.StatusBadRequest, api.ErrorResponseDetailsNotSortable, request), response)
return
}

if descending {
order = append(order, column+" desc")
} else {
order = append(order, column)
}
}
iustinum marked this conversation as resolved.
Show resolved Hide resolved

// Set default order by created_at if no sorting is specified
if len(order) == 0 {
order = append(order, "created_at")
}

if queryFilters, err = queryFilterParser.ParseQueryParameterFilters(request); err != nil {
api.WriteErrorResponse(ctx, api.BuildErrorResponse(http.StatusBadRequest, api.ErrorResponseDetailsBadQueryParameterFilters, request), response)
return
iustinum marked this conversation as resolved.
Show resolved Hide resolved
} else {
for name, filters := range queryFilters {
if validPredicates, err := model.SSOProviderValidFilterPredicates(name); err != nil {
api.WriteErrorResponse(ctx, api.BuildErrorResponse(http.StatusBadRequest, err.Error(), request), response)
return
} else {
for i, filter := range filters {
if !utils.Contains(validPredicates, string(filter.Operator)) {
api.WriteErrorResponse(ctx, api.BuildErrorResponse(http.StatusBadRequest, api.ErrorResponseDetailsFilterPredicateNotSupported, request), response)
return
}
queryFilters[name][i].IsStringData = model.SSOProviderIsStringField(filter.Name)
}
}
}
iustinum marked this conversation as resolved.
Show resolved Hide resolved

if sqlFilter, err = queryFilters.BuildSQLFilter(); err != nil {
api.WriteErrorResponse(ctx, api.BuildErrorResponse(http.StatusBadRequest, "error building SQL for filter", request), response)
return
iustinum marked this conversation as resolved.
Show resolved Hide resolved
} else if ssoProviders, err = s.db.GetAllSSOProviders(ctx, strings.Join(order, ", "), sqlFilter); err != nil {
api.HandleDatabaseError(request, response, err)
return
iustinum marked this conversation as resolved.
Show resolved Hide resolved
} else {
for _, ssoProvider := range ssoProviders {
provider := AuthProvider{
ID: ssoProvider.ID,
Name: ssoProvider.Name,
Type: ssoProvider.Type.String(),
Slug: ssoProvider.Slug,
}

switch ssoProvider.Type {
case model.SessionAuthProviderOIDC:
if ssoProvider.OIDCProvider != nil {
provider.Details = ssoProvider.OIDCProvider
}
case model.SessionAuthProviderSAML:
if ssoProvider.SAMLProvider != nil {
provider.Details = ssoProvider.SAMLProvider
}
}

providers = append(providers, provider)
}

api.WriteBasicResponse(ctx, providers, http.StatusOK, response)
}
}
}
Loading
Loading