mirror of
https://github.com/netbirdio/netbird.git
synced 2024-12-16 03:41:26 +01:00
765aba2c1c
propagate context from all the API calls and log request ID, account ID and peer ID --------- Co-authored-by: Zoltan Papp <zoltan.pmail@gmail.com>
189 lines
6.5 KiB
Go
189 lines
6.5 KiB
Go
package idp
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/netbirdio/netbird/management/server/telemetry"
|
|
)
|
|
|
|
const (
|
|
// UnsetAccountID is a special key to map users without an account ID
|
|
UnsetAccountID = "unset"
|
|
)
|
|
|
|
// Manager idp manager interface
|
|
type Manager interface {
|
|
UpdateUserAppMetadata(ctx context.Context, userId string, appMetadata AppMetadata) error
|
|
GetUserDataByID(ctx context.Context, userId string, appMetadata AppMetadata) (*UserData, error)
|
|
GetAccount(ctx context.Context, accountId string) ([]*UserData, error)
|
|
GetAllAccounts(ctx context.Context) (map[string][]*UserData, error)
|
|
CreateUser(ctx context.Context, email, name, accountID, invitedByEmail string) (*UserData, error)
|
|
GetUserByEmail(ctx context.Context, email string) ([]*UserData, error)
|
|
InviteUserByID(ctx context.Context, userID string) error
|
|
DeleteUser(ctx context.Context, userID string) error
|
|
}
|
|
|
|
// ClientConfig defines common client configuration for all IdP manager
|
|
type ClientConfig struct {
|
|
Issuer string
|
|
TokenEndpoint string
|
|
ClientID string
|
|
ClientSecret string
|
|
GrantType string
|
|
}
|
|
|
|
// ExtraConfig stores IdP specific config that are unique to individual IdPs
|
|
type ExtraConfig map[string]string
|
|
|
|
// Config an idp configuration struct to be loaded from management server's config file
|
|
type Config struct {
|
|
ManagerType string
|
|
ClientConfig *ClientConfig
|
|
ExtraConfig ExtraConfig
|
|
Auth0ClientCredentials *Auth0ClientConfig
|
|
AzureClientCredentials *AzureClientConfig
|
|
KeycloakClientCredentials *KeycloakClientConfig
|
|
ZitadelClientCredentials *ZitadelClientConfig
|
|
}
|
|
|
|
// ManagerCredentials interface that authenticates using the credential of each type of idp
|
|
type ManagerCredentials interface {
|
|
Authenticate(ctx context.Context) (JWTToken, error)
|
|
}
|
|
|
|
// ManagerHTTPClient http client interface for API calls
|
|
type ManagerHTTPClient interface {
|
|
Do(req *http.Request) (*http.Response, error)
|
|
}
|
|
|
|
// ManagerHelper helper
|
|
type ManagerHelper interface {
|
|
Marshal(v interface{}) ([]byte, error)
|
|
Unmarshal(data []byte, v interface{}) error
|
|
}
|
|
|
|
type UserData struct {
|
|
Email string `json:"email"`
|
|
Name string `json:"name"`
|
|
ID string `json:"user_id"`
|
|
AppMetadata AppMetadata `json:"app_metadata"`
|
|
}
|
|
|
|
// AppMetadata user app metadata to associate with a profile
|
|
type AppMetadata struct {
|
|
// WTAccountID is a NetBird (previously Wiretrustee) account id to update in the IDP
|
|
// maps to wt_account_id when json.marshal
|
|
WTAccountID string `json:"wt_account_id,omitempty"`
|
|
WTPendingInvite *bool `json:"wt_pending_invite,omitempty"`
|
|
WTInvitedBy string `json:"wt_invited_by_email,omitempty"`
|
|
}
|
|
|
|
// JWTToken a JWT object that holds information of a token
|
|
type JWTToken struct {
|
|
AccessToken string `json:"access_token"`
|
|
ExpiresIn int `json:"expires_in"`
|
|
expiresInTime time.Time
|
|
Scope string `json:"scope"`
|
|
TokenType string `json:"token_type"`
|
|
}
|
|
|
|
// NewManager returns a new idp manager based on the configuration that it receives
|
|
func NewManager(ctx context.Context, config Config, appMetrics telemetry.AppMetrics) (Manager, error) {
|
|
if config.ClientConfig != nil {
|
|
config.ClientConfig.Issuer = strings.TrimSuffix(config.ClientConfig.Issuer, "/")
|
|
}
|
|
|
|
switch strings.ToLower(config.ManagerType) {
|
|
case "none", "":
|
|
return nil, nil //nolint:nilnil
|
|
case "auth0":
|
|
auth0ClientConfig := config.Auth0ClientCredentials
|
|
if config.ClientConfig != nil {
|
|
auth0ClientConfig = &Auth0ClientConfig{
|
|
Audience: config.ExtraConfig["Audience"],
|
|
AuthIssuer: config.ClientConfig.Issuer,
|
|
ClientID: config.ClientConfig.ClientID,
|
|
ClientSecret: config.ClientConfig.ClientSecret,
|
|
GrantType: config.ClientConfig.GrantType,
|
|
}
|
|
}
|
|
|
|
return NewAuth0Manager(*auth0ClientConfig, appMetrics)
|
|
case "azure":
|
|
azureClientConfig := config.AzureClientCredentials
|
|
if config.ClientConfig != nil {
|
|
azureClientConfig = &AzureClientConfig{
|
|
ClientID: config.ClientConfig.ClientID,
|
|
ClientSecret: config.ClientConfig.ClientSecret,
|
|
GrantType: config.ClientConfig.GrantType,
|
|
TokenEndpoint: config.ClientConfig.TokenEndpoint,
|
|
ObjectID: config.ExtraConfig["ObjectId"],
|
|
GraphAPIEndpoint: config.ExtraConfig["GraphApiEndpoint"],
|
|
}
|
|
}
|
|
|
|
return NewAzureManager(*azureClientConfig, appMetrics)
|
|
case "keycloak":
|
|
keycloakClientConfig := config.KeycloakClientCredentials
|
|
if config.ClientConfig != nil {
|
|
keycloakClientConfig = &KeycloakClientConfig{
|
|
ClientID: config.ClientConfig.ClientID,
|
|
ClientSecret: config.ClientConfig.ClientSecret,
|
|
GrantType: config.ClientConfig.GrantType,
|
|
TokenEndpoint: config.ClientConfig.TokenEndpoint,
|
|
AdminEndpoint: config.ExtraConfig["AdminEndpoint"],
|
|
}
|
|
}
|
|
|
|
return NewKeycloakManager(*keycloakClientConfig, appMetrics)
|
|
case "zitadel":
|
|
zitadelClientConfig := config.ZitadelClientCredentials
|
|
if config.ClientConfig != nil {
|
|
zitadelClientConfig = &ZitadelClientConfig{
|
|
ClientID: config.ClientConfig.ClientID,
|
|
ClientSecret: config.ClientConfig.ClientSecret,
|
|
GrantType: config.ClientConfig.GrantType,
|
|
TokenEndpoint: config.ClientConfig.TokenEndpoint,
|
|
ManagementEndpoint: config.ExtraConfig["ManagementEndpoint"],
|
|
}
|
|
}
|
|
|
|
return NewZitadelManager(*zitadelClientConfig, appMetrics)
|
|
case "authentik":
|
|
authentikConfig := AuthentikClientConfig{
|
|
Issuer: config.ClientConfig.Issuer,
|
|
ClientID: config.ClientConfig.ClientID,
|
|
TokenEndpoint: config.ClientConfig.TokenEndpoint,
|
|
GrantType: config.ClientConfig.GrantType,
|
|
Username: config.ExtraConfig["Username"],
|
|
Password: config.ExtraConfig["Password"],
|
|
}
|
|
return NewAuthentikManager(authentikConfig, appMetrics)
|
|
case "okta":
|
|
oktaClientConfig := OktaClientConfig{
|
|
Issuer: config.ClientConfig.Issuer,
|
|
TokenEndpoint: config.ClientConfig.TokenEndpoint,
|
|
GrantType: config.ClientConfig.GrantType,
|
|
APIToken: config.ExtraConfig["ApiToken"],
|
|
}
|
|
return NewOktaManager(oktaClientConfig, appMetrics)
|
|
case "google":
|
|
googleClientConfig := GoogleWorkspaceClientConfig{
|
|
ServiceAccountKey: config.ExtraConfig["ServiceAccountKey"],
|
|
CustomerID: config.ExtraConfig["CustomerId"],
|
|
}
|
|
return NewGoogleWorkspaceManager(ctx, googleClientConfig, appMetrics)
|
|
case "jumpcloud":
|
|
jumpcloudConfig := JumpCloudClientConfig{
|
|
APIToken: config.ExtraConfig["ApiToken"],
|
|
}
|
|
return NewJumpCloudManager(jumpcloudConfig, appMetrics)
|
|
default:
|
|
return nil, fmt.Errorf("invalid manager type: %s", config.ManagerType)
|
|
}
|
|
}
|