Skip to content

Commit e2e7dc6

Browse files
Authentik Github SSO (#246)
<!-- ELLIPSIS_HIDDEN --> > [!IMPORTANT] > Introduces `authentik_github_sso` module for Authentik-GitHub SAML SSO integration, focusing on authentication without user provisioning. > > - **New Module**: > - Adds `authentik_github_sso` module for integrating Authentik with GitHub SAML SSO. > - Handles authentication only; does not support user provisioning or de-provisioning. > - Requires GitHub Enterprise plan. > - **Configuration**: > - Includes `main.tf`, `vars.tf`, `outputs.tf`, and `config.yaml` for Terraform setup. > - Uses providers: `authentik`, `kubernetes`, `kubectl`, `random`, `tls`. > - **Documentation**: > - Adds `README.md` and `index.mdx` with setup guide and usage instructions. > - Updates `changelog/edge.mdx` and `modules.json` to include the new module. > - **Setup Guide**: > - Provides step-by-step instructions for configuring SAML SSO at the enterprise level. > - Details on deploying GitHub provider and application in Authentik. > > <sup>This description was created by </sup>[<img alt="Ellipsis" src="https://img.shields.io/badge/Ellipsis-blue?color=175173">](https://www.ellipsis.dev?ref=Panfactum%2Fstack&utm_source=github&utm_medium=referral)<sup> for 9ff13b2. It will automatically update as commits are pushed.</sup> <!-- ELLIPSIS_HIDDEN --> --------- Signed-off-by: James Lee <[email protected]> Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
1 parent ab20465 commit e2e7dc6

File tree

19 files changed

+639
-1
lines changed

19 files changed

+639
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
## Maintainer Notes
2+
3+
No notes
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import MarkdownAlert from "@/components/markdown/MarkdownAlert.astro";
2+
3+
# Authentik GitHub SSO
4+
5+
This module configures Authentik for integration with GitHub SAML single sign-on.
6+
7+
***Note:*** The [GitHub Enterprise plan](https://docs.github.com/en/enterprise-cloud@latest/admin/managing-iam/using-saml-for-enterprise-iam/configuring-saml-single-sign-on-for-your-enterprise) is required for SSO.
8+
9+
<MarkdownAlert severity="warning">
10+
Due to limitations with GitHub, this module only handles authentication and does not support user provisioning or de-provisioning at this time. As a result, users will not be automatically created or removed from GitHub when they are added or removed from Authentik.
11+
12+
When a user is removed from Authentik, they will lose access to the organization. However, be aware of the following caveats:
13+
- Any active session tokens that the user has with the GitHub web UI and PATs the user may have generated will not be automatically revoked. Until these tokens expire, the user may still interact with the web UI / API unless they are manually removed from the GitHub organization.
14+
</MarkdownAlert>
15+
16+
## Guide
17+
18+
<MarkdownAlert severity="warning">
19+
This guide sets up SAML SSO at the enterprise level, not the organization level. This is important because:
20+
- An enterprise-level integration provides SSO coverage for all organizations within your GitHub Enterprise
21+
- This eliminates the need to configure separate SSO integrations for each organization
22+
- All authentication will be managed through a single integration point
23+
24+
While this guide focuses on enterprise-level setup, the same steps can be followed for organization-level SSO by selecting the organization settings instead of enterprise settings in GitHub.
25+
</MarkdownAlert>
26+
27+
### Start the GitHub SAML SSO Setup
28+
29+
1. Log in to GitHub and navigate to your enterprise's dashboard. For example, Panfactum's enterprise url is https://github.com/enterprises/Panfactum.
30+
1. Click on your profile picture in the top right corner.
31+
2. Select `Your enterprises`.
32+
3. Click on `settings` for your enterprise name.
33+
2. Go to Authentication security.
34+
3. Toggle on `Require SAML authentication`.
35+
4. Note the `assertion consumer service URL`. We will use this in the following step.
36+
![GitHub ACS URL](doc_images/github-acs-url.png)
37+
38+
39+
### Deploy GitHub Provider & Application in Authentik
40+
41+
1. Add a new `authentik_github_sso` folder adjacent to your `authentik_core_resources` folder.
42+
2. Add a new `terragrunt.hcl` file that looks like [this](https://github.com/Panfactum/stack/blob/__PANFACTUM_VERSION_MAIN__/packages/reference/environments/production/us-east-2/authentik_github_sso/terragrunt.hcl).
43+
3. Set the `acs_url` input using the `assertion consumer service URL` from above.
44+
4. Run `pf-tf-init`.
45+
5. Run `terragrunt apply`.
46+
6. Note the output as you'll use it in the following steps.
47+
48+
### Complete GitHub SAML single sign-on
49+
50+
1. Resume the Authentication security page
51+
2. Go to Security -> Authentication security.
52+
3. Set `Sign on URL` with the `sso_post_url` output value from above.
53+
4. Set `Issuer` with the `issuer_url` output value from above.
54+
5. Set `Public certificate` from the `certificate` output value from above.
55+
![SAML Form](doc_images/github-saml-form.png)
56+
6. Click on `Test SAML configuration`.
57+
7. Save the `recovery codes` that you are prompted with.
58+
8. Click on `Save`.
59+
60+
### Test and Validate the Integration
61+
62+
1. Go to your Authentik instance.
63+
2. Find the GitHub application. Ensure you are in the user dashboard, not the admin dashboard.
64+
![GitHub Application](doc_images/github-application.png)
65+
3. Click and confirm that you are able to login.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
type: direct
2+
status: stable
3+
group: authentik
Loading
Loading
Loading
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
terraform {
2+
required_providers {
3+
authentik = {
4+
source = "goauthentik/authentik"
5+
version = "2024.8.4"
6+
}
7+
kubernetes = {
8+
source = "hashicorp/kubernetes"
9+
version = "2.34.0"
10+
}
11+
kubectl = {
12+
source = "alekc/kubectl"
13+
version = "2.1.3"
14+
}
15+
random = {
16+
source = "hashicorp/random"
17+
version = "3.6.3"
18+
}
19+
tls = {
20+
source = "hashicorp/tls"
21+
version = "4.0.6"
22+
}
23+
}
24+
}
25+
26+
locals {
27+
combined_allowed_groups = toset([
28+
"superusers",
29+
"privileged_engineers",
30+
"engineers",
31+
"restricted_engineers",
32+
"billing_admins"], var.extra_allowed_groups...)
33+
34+
issuer = "https://${var.authentik_domain}"
35+
}
36+
37+
###########################################################################
38+
## Upload the logo
39+
###########################################################################
40+
41+
resource "random_id" "logo" {
42+
prefix = "github-"
43+
byte_length = 8
44+
}
45+
46+
resource "kubernetes_config_map_v1_data" "media" {
47+
metadata {
48+
name = var.media_configmap
49+
namespace = var.authentik_namespace
50+
}
51+
data = {
52+
"${random_id.logo.hex}.svg" = file("${path.module}/github.svg")
53+
}
54+
field_manager = random_id.logo.hex
55+
force = true
56+
}
57+
58+
###########################################################################
59+
## Cert Config
60+
###########################################################################
61+
62+
// These certs are only used for their random cryptographic
63+
// material to sign the SAML assertions. There is no
64+
// need to use cert-manager to manage them,
65+
// especially since they need to be manually uploaded to github
66+
// every time they rotate
67+
resource "tls_private_key" "signing" {
68+
algorithm = "RSA"
69+
rsa_bits = 4096
70+
}
71+
72+
resource "tls_self_signed_cert" "signing" {
73+
private_key_pem = tls_private_key.signing.private_key_pem
74+
subject {
75+
common_name = var.authentik_domain
76+
organization = var.organization_name
77+
}
78+
validity_period_hours = 24 * 365 * 10
79+
allowed_uses = [
80+
"key_encipherment",
81+
"digital_signature",
82+
"server_auth",
83+
]
84+
}
85+
86+
resource "authentik_certificate_key_pair" "signing" {
87+
name = "github-signing-certs"
88+
certificate_data = tls_self_signed_cert.signing.cert_pem
89+
key_data = tls_private_key.signing.private_key_pem
90+
}
91+
92+
###########################################################################
93+
## IdP Config
94+
###########################################################################
95+
96+
data "authentik_flow" "default_authorization_flow" {
97+
slug = "default-provider-authorization-implicit-consent"
98+
}
99+
100+
data "authentik_property_mapping_provider_saml" "email" {
101+
managed = "goauthentik.io/providers/saml/email"
102+
}
103+
104+
resource "authentik_provider_saml" "github" {
105+
name = "github"
106+
authorization_flow = data.authentik_flow.default_authorization_flow.id
107+
property_mappings = [data.authentik_property_mapping_provider_saml.email.id]
108+
acs_url = var.acs_url
109+
sp_binding = "post"
110+
issuer = local.issuer
111+
audience = replace(var.acs_url, "/saml/consume", "")
112+
name_id_mapping = data.authentik_property_mapping_provider_saml.email.id
113+
signing_kp = authentik_certificate_key_pair.signing.id
114+
}
115+
116+
resource "null_resource" "wait_for_saml_provider" {
117+
depends_on = [authentik_provider_saml.github]
118+
119+
provisioner "local-exec" {
120+
command = "sleep 10" # Give the API time to fully create the resource
121+
}
122+
}
123+
124+
resource "authentik_application" "github" {
125+
name = "GitHub"
126+
slug = "github"
127+
protocol_provider = authentik_provider_saml.github.id
128+
meta_description = var.ui_description
129+
meta_publisher = "Panfactum"
130+
meta_icon = "https://${var.authentik_domain}/media/public/${random_id.logo.hex}.svg"
131+
open_in_new_tab = true
132+
}
133+
134+
data "authentik_group" "group" {
135+
for_each = local.combined_allowed_groups
136+
name = each.key
137+
}
138+
139+
resource "authentik_policy_binding" "access" {
140+
for_each = local.combined_allowed_groups
141+
target = authentik_application.github.uuid
142+
group = data.authentik_group.group[each.key].id
143+
order = 10
144+
}
145+
146+
data "authentik_provider_saml_metadata" "github" {
147+
provider_id = authentik_provider_saml.github.id
148+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
output "saml_metadata" {
2+
description = "The SAML metadata for the GitHub provider. https://en.wikipedia.org/wiki/SAML_metadata"
3+
value = data.authentik_provider_saml_metadata.github.metadata
4+
}
5+
6+
output "sso_post_url" {
7+
description = "The URL where SAML authentication requests are sent from the Service Provider (GitHub)"
8+
value = authentik_provider_saml.github.url_sso_redirect
9+
}
10+
11+
output "issuer_url" {
12+
description = "The Authentik issuer URL for the GitHub provider"
13+
value = local.issuer
14+
}
15+
16+
output "certificate" {
17+
description = "The certificate used to sign SAML responses"
18+
value = authentik_certificate_key_pair.signing.certificate_data
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
variable "media_configmap" {
2+
description = "The ConfigMap holding the static media that Authentik will use"
3+
type = string
4+
default = "media"
5+
}
6+
7+
variable "authentik_namespace" {
8+
description = "The kubernetes namespace where Authentik is deployed"
9+
type = string
10+
default = "authentik"
11+
}
12+
13+
variable "authentik_domain" {
14+
description = "The domain name of the Authentik instance"
15+
type = string
16+
}
17+
18+
variable "organization_name" {
19+
description = "The name of your organization"
20+
type = string
21+
}
22+
23+
variable "acs_url" {
24+
description = "The ACS url provided by GitHub when configuring an external identity provider"
25+
type = string
26+
}
27+
28+
variable "ui_description" {
29+
description = "The description to display in the Authentik web dashboard"
30+
type = string
31+
default = "GitHub"
32+
}
33+
34+
variable "extra_allowed_groups" {
35+
description = "Additional groups that can access GitHub"
36+
type = set(string)
37+
default = []
38+
}

0 commit comments

Comments
 (0)