Skip to content

Commit

Permalink
Merge pull request #4749 from opsmill/pog-sso-infrahub-toml
Browse files Browse the repository at this point in the history
Support SSO provider config from infrahub.toml
  • Loading branch information
ogenstad authored Oct 28, 2024
2 parents 9c85693 + 612b56e commit 56dfb3c
Show file tree
Hide file tree
Showing 2 changed files with 174 additions and 34 deletions.
54 changes: 48 additions & 6 deletions backend/infrahub/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,14 @@ class SecurityOIDCProvider2(SecurityOIDCSettings):
model_config = SettingsConfigDict(env_prefix="INFRAHUB_OIDC_PROVIDER2_")


class SecurityOIDCProviderSettings(BaseModel):
"""This class is meant to facilitate configuration of OIDC providers when loading configuration from a infrahub.toml file."""

google: Optional[SecurityOIDCGoogle] = Field(default=None)
provider1: Optional[SecurityOIDCProvider1] = Field(default=None)
provider2: Optional[SecurityOIDCProvider2] = Field(default=None)


class SecurityOAuth2BaseSettings(BaseSettings):
"""Baseclass for typing"""

Expand Down Expand Up @@ -490,6 +498,14 @@ class SecurityOAuth2Google(SecurityOAuth2Settings):
display_label: str = Field(default="Google")


class SecurityOAuth2ProviderSettings(BaseModel):
"""This class is meant to facilitate configuration of OAuth2 providers when loading configuration from a infrahub.toml file."""

google: Optional[SecurityOAuth2Google] = Field(default=None)
provider1: Optional[SecurityOAuth2Provider1] = Field(default=None)
provider2: Optional[SecurityOAuth2Provider2] = Field(default=None)


class MiscellaneousSettings(BaseSettings):
model_config = SettingsConfigDict(env_prefix="INFRAHUB_MISC_")
print_query_details: bool = False
Expand Down Expand Up @@ -535,7 +551,9 @@ class SecuritySettings(BaseSettings):
default_factory=generate_uuid, description="The secret key used to validate authentication tokens"
)
oauth2_providers: list[Oauth2Provider] = Field(default_factory=list, description="The selected OAuth2 providers")
oauth2_provider_settings: SecurityOAuth2ProviderSettings = Field(default_factory=SecurityOAuth2ProviderSettings)
oidc_providers: list[OIDCProvider] = Field(default_factory=list, description="The selected OIDC providers")
oidc_provider_settings: SecurityOIDCProviderSettings = Field(default_factory=SecurityOIDCProviderSettings)
_oauth2_settings: dict[str, SecurityOAuth2Settings] = PrivateAttr(default_factory=dict)
_oidc_settings: dict[str, SecurityOIDCSettings] = PrivateAttr(default_factory=dict)

Expand All @@ -547,9 +565,21 @@ def check_oauth2_provider_settings(self) -> Self:
Oauth2Provider.GOOGLE: SecurityOAuth2Google,
}
for oauth2_provider in self.oauth2_providers:
provider = mapped_providers[oauth2_provider]()
if isinstance(provider, SecurityOAuth2Settings):
self._oauth2_settings[oauth2_provider.value] = provider
match oauth2_provider:
case Oauth2Provider.GOOGLE:
if self.oauth2_provider_settings.google:
self._oauth2_settings[oauth2_provider.value] = self.oauth2_provider_settings.google
case Oauth2Provider.PROVIDER1:
if self.oauth2_provider_settings.provider1:
self._oauth2_settings[oauth2_provider.value] = self.oauth2_provider_settings.provider1
case Oauth2Provider.PROVIDER2:
if self.oauth2_provider_settings.provider2:
self._oauth2_settings[oauth2_provider.value] = self.oauth2_provider_settings.provider2

if oauth2_provider.value not in self._oauth2_settings:
provider = mapped_providers[oauth2_provider]()
if isinstance(provider, SecurityOAuth2Settings):
self._oauth2_settings[oauth2_provider.value] = provider

return self

Expand All @@ -561,9 +591,21 @@ def check_oidc_provider_settings(self) -> Self:
OIDCProvider.PROVIDER2: SecurityOIDCProvider2,
}
for oidc_provider in self.oidc_providers:
provider = mapped_providers[oidc_provider]()
if isinstance(provider, SecurityOIDCSettings):
self._oidc_settings[oidc_provider.value] = provider
match oidc_provider:
case OIDCProvider.GOOGLE:
if self.oidc_provider_settings.google:
self._oidc_settings[oidc_provider.value] = self.oidc_provider_settings.google
case OIDCProvider.PROVIDER1:
if self.oidc_provider_settings.provider1:
self._oidc_settings[oidc_provider.value] = self.oidc_provider_settings.provider1
case OIDCProvider.PROVIDER2:
if self.oidc_provider_settings.provider2:
self._oidc_settings[oidc_provider.value] = self.oidc_provider_settings.provider2

if oidc_provider.value not in self._oidc_settings:
provider = mapped_providers[oidc_provider]()
if isinstance(provider, SecurityOIDCSettings):
self._oidc_settings[oidc_provider.value] = provider

return self

Expand Down
154 changes: 126 additions & 28 deletions docs/docs/guides/sso.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
---
title: Configuring Single sign-on
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

# Configuring Single sign-on

In Infrahub you can configure SSO using either Open ID Connect (OIDC) or can use OAuth2.
Expand Down Expand Up @@ -40,31 +43,80 @@ Aside from the display label and icon all the other entries will be provided by

An example of what the configuration could look like:

```bash
export INFRAHUB_OAUTH2_PROVIDER1_CLIENT_ID=infrahub-sso
export INFRAHUB_OAUTH2_PROVIDER1_CLIENT_SECRET=edPf4IaquQaqns7t3s95mLhKKYdwL1up
export INFRAHUB_OAUTH2_PROVIDER1_AUTHORIZATION_URL=http://localhost:8180/realms/infrahub/protocol/openid-connect/auth
export INFRAHUB_OAUTH2_PROVIDER1_TOKEN_URL=http://localhost:8180/realms/infrahub/protocol/openid-connect/token
export INFRAHUB_OAUTH2_PROVIDER1_USERINFO_URL=http://localhost:8180/realms/infrahub/protocol/openid-connect/userinfo
export INFRAHUB_OAUTH2_PROVIDER1_DISPLAY_LABEL="Internal Server (Keycloak)"
export INFRAHUB_OAUTH2_PROVIDER1_ICON="mdi:security-lock-outline"
```
<Tabs groupId="provider1-configuration">
<TabItem value="Environment Variables" default>

```bash
export INFRAHUB_OAUTH2_PROVIDER1_CLIENT_ID=infrahub-sso
export INFRAHUB_OAUTH2_PROVIDER1_CLIENT_SECRET=edPf4IaquQaqns7t3s95mLhKKYdwL1up
export INFRAHUB_OAUTH2_PROVIDER1_AUTHORIZATION_URL=http://localhost:8180/realms/infrahub/protocol/openid-connect/auth
export INFRAHUB_OAUTH2_PROVIDER1_TOKEN_URL=http://localhost:8180/realms/infrahub/protocol/openid-connect/token
export INFRAHUB_OAUTH2_PROVIDER1_USERINFO_URL=http://localhost:8180/realms/infrahub/protocol/openid-connect/userinfo
export INFRAHUB_OAUTH2_PROVIDER1_DISPLAY_LABEL="Internal Server (Keycloak)"
export INFRAHUB_OAUTH2_PROVIDER1_ICON="mdi:security-lock-outline"
```

</TabItem>
<TabItem value="infrahub.toml" default>

```toml
[security.oauth2_provider_settings.provider1]
client_id = "infrahub-sso"
client_secret = "edPf4IaquQaqns7t3s95mLhKKYdwL1up"
authorization_url = "http://localhost:8180/realms/infrahub/protocol/openid-connect/auth"
token_url = "http://localhost:8180/realms/infrahub/protocol/openid-connect/token"
userinfo_url = "http://localhost:8180/realms/infrahub/protocol/openid-connect/userinfo"
scopes = ["openid", "profile", "email"]
display_label = "Internal Server (Keycloak)"
icon = "mdi:security-lock-outline"
```

</TabItem>
</Tabs>

This could be the configuration of a Keycloak provider, please refer to the documentation of your intended provider for guides on how to create a client and access the required information.

## Activating the OAuth2 provider

In order to activate the above provider we need to add it to the list of active OAuth2 providers.

```bash
export INFRAHUB_SECURITY_OAUTH2_PROVIDERS='["provider1"]'
```
<Tabs groupId="provider1-configuration">
<TabItem value="Environment Variables" default>

```bash
export INFRAHUB_SECURITY_OAUTH2_PROVIDERS='["provider1"]'
```

</TabItem>
<TabItem value="infrahub.toml" default>

```toml
[security]
oauth2_providers = ["provider1"]
```

</TabItem>
</Tabs>

Alternatively if you are setting up multiple providers each with their different settings:

```bash
export INFRAHUB_SECURITY_OAUTH2_PROVIDERS='["provider1","provider2"]'
```
<Tabs groupId="provider1-configuration">
<TabItem value="Environment Variables" default>

```bash
export INFRAHUB_SECURITY_OAUTH2_PROVIDERS='["provider1","provider2"]'
```

</TabItem>
<TabItem value="infrahub.toml" default>

```toml
[security]
oauth2_providers = ["provider1", "provider2"]
```

</TabItem>
</Tabs>

## Setting up OIDC in Infrahub

Expand All @@ -89,29 +141,75 @@ Aside from the display label and icon all the other entries will be provided by

An example of what the configuration could look like:

```bash
export INFRAHUB_OIDC_PROVIDER1_CLIENT_ID=infrahub-sso
export INFRAHUB_OIDC_PROVIDER1_CLIENT_SECRET=edPf4IaquQaqns7t3s95mLhKKYdwL1up
export INFRAHUB_OIDC_PROVIDER1_DISCOVERY_URL=http://localhost:8180/realms/infrahub/.well-known/openid-configuration
export INFRAHUB_OIDC_PROVIDER1_DISPLAY_LABEL="Internal Server (Keycloak)"
export INFRAHUB_OIDC_PROVIDER1_ICON="mdi:security-lock-outline"
```
<Tabs groupId="provider1-configuration">
<TabItem value="Environment Variables" default>

```bash
export INFRAHUB_OIDC_PROVIDER1_CLIENT_ID=infrahub-sso
export INFRAHUB_OIDC_PROVIDER1_CLIENT_SECRET=edPf4IaquQaqns7t3s95mLhKKYdwL1up
export INFRAHUB_OIDC_PROVIDER1_DISCOVERY_URL=http://localhost:8180/realms/infrahub/.well-known/openid-configuration
export INFRAHUB_OIDC_PROVIDER1_DISPLAY_LABEL="Internal Server (Keycloak)"
export INFRAHUB_OIDC_PROVIDER1_ICON="mdi:security-lock-outline"
```

</TabItem>
<TabItem value="infrahub.toml" default>

```toml
[security.oidc_provider_settings.provider1]
client_id = "infrahub-sso"
client_secret = "edPf4IaquQaqns7t3s95mLhKKYdwL1up"
discovery_url = "http://localhost:8180/realms/infrahub/.well-known/openid-configuration"
display_label = "Internal Server (Keycloak)"
icon = "mdi:security-lock-outline"
```

</TabItem>
</Tabs>

This could be the configuration of a Keycloak provider, please refer to the documentation of your intended provider for guides on how to create a client and access the required information.

## Activating the OIDC provider

In order to activate the above provider we need to add it to the list of active OIDC providers.

```bash
export INFRAHUB_SECURITY_OIDC_PROVIDERS='["provider1"]'
```
<Tabs groupId="provider1-configuration">
<TabItem value="Environment Variables" default>

```bash
export INFRAHUB_SECURITY_OIDC_PROVIDERS='["provider1"]'
```

</TabItem>
<TabItem value="infrahub.toml" default>

```toml
[security]
oidc_providers = ["provider1"]
```

</TabItem>
</Tabs>

Alternatively if you are setting up multiple providers each with their different settings:

```bash
export INFRAHUB_SECURITY_OIDC_PROVIDERS='["provider1","provider2"]'
```
<Tabs groupId="provider1-configuration">
<TabItem value="Environment Variables" default>

```bash
export INFRAHUB_SECURITY_OIDC_PROVIDERS='["provider1","provider2"]'
```

</TabItem>
<TabItem value="infrahub.toml" default>

```toml
[security]
oidc_providers = ["provider1", "provider2"]
```

</TabItem>
</Tabs>

## Configuring the redirect URI in the identity provider

Expand Down

0 comments on commit 56dfb3c

Please sign in to comment.