forked from dexidp/dex
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Andy Lo-A-Foe <[email protected]>
- Loading branch information
Showing
9 changed files
with
1,111 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
name: Fork Artifacts | ||
|
||
on: | ||
push: | ||
branches: | ||
- master | ||
tags: | ||
- '*' | ||
pull_request: | ||
|
||
jobs: | ||
container-images: | ||
name: Container images | ||
runs-on: ubuntu-latest | ||
strategy: | ||
matrix: | ||
variant: | ||
- alpine | ||
- distroless | ||
|
||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@v3 | ||
|
||
- name: Gather metadata | ||
id: meta | ||
uses: docker/metadata-action@v4 | ||
with: | ||
images: | | ||
ghcr.io/philips-forks/dex | ||
flavor: | | ||
latest = false | ||
tags: | | ||
type=ref,event=branch,enable=${{ matrix.variant == 'alpine' }} | ||
type=ref,event=pr,enable=${{ matrix.variant == 'alpine' }} | ||
type=semver,pattern={{raw}},enable=${{ matrix.variant == 'alpine' }} | ||
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && matrix.variant == 'alpine' }} | ||
type=ref,event=branch,suffix=-${{ matrix.variant }} | ||
type=ref,event=pr,suffix=-${{ matrix.variant }} | ||
type=semver,pattern={{raw}},suffix=-${{ matrix.variant }} | ||
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) }},suffix=-${{ matrix.variant }} | ||
labels: | | ||
org.opencontainers.image.documentation=https://dexidp.io/docs/ | ||
- name: Set up QEMU | ||
uses: docker/setup-qemu-action@v2 | ||
with: | ||
platforms: all | ||
|
||
- name: Set up Docker Buildx | ||
uses: docker/setup-buildx-action@v2 | ||
|
||
- name: Login to GitHub Container Registry | ||
uses: docker/login-action@v2 | ||
with: | ||
registry: ghcr.io | ||
username: ${{ github.repository_owner }} | ||
password: ${{ github.token }} | ||
if: github.event_name == 'push' | ||
|
||
- name: Build and push | ||
uses: docker/build-push-action@v4 | ||
with: | ||
context: . | ||
platforms: linux/amd64,linux/arm64 | ||
# cache-from: type=gha | ||
# cache-to: type=gha,mode=max | ||
push: ${{ github.event_name == 'push' }} | ||
tags: ${{ steps.meta.outputs.tags }} | ||
build-args: | | ||
BASE_IMAGE=${{ matrix.variant }} | ||
VERSION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.version'] }} | ||
COMMIT_HASH=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.revision'] }} | ||
BUILD_DATE=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.created'] }} | ||
labels: ${{ steps.meta.outputs.labels }} | ||
|
||
- name: Run Trivy vulnerability scanner | ||
uses: aquasecurity/[email protected] | ||
with: | ||
image-ref: "ghcr.io/philips-forks/dex:${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.version'] }}" | ||
format: "sarif" | ||
output: "trivy-results.sarif" | ||
if: github.event_name == 'push' | ||
|
||
- name: Upload Trivy scan results to GitHub Security tab | ||
uses: github/codeql-action/upload-sarif@v2 | ||
with: | ||
sarif_file: "trivy-results.sarif" | ||
if: github.event_name == 'push' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
# hsdp connector | ||
|
||
This connector supports [HSP IAM](https://www.hsdp.io/documentation/identity-and-access-management-iam/getting-started) as an upstream IDP for Dex. | ||
|
||
# helm chart | ||
|
||
Dex is deployed using the [helm chart](https://artifacthub.io/packages/helm/dex/dex) from the [Artifact Hub](https://artifacthub.io/). | ||
|
||
# configuration | ||
|
||
When deploying Dex with the HSP IAM connector, you need to configure the connector in the Dex configuration file. | ||
Helm chart users can configure the connector in the `values.yaml` file. | ||
|
||
Connector section example: | ||
|
||
```yaml | ||
connectors: | ||
- type: hsdp | ||
id: hsdp | ||
name: Philips Code1 | ||
config: | ||
trustedOrgID: 8a67a785-73bb-46d5-b73f-d951a6d3cb43 | ||
tenantMap: | ||
dae89cf0-888d-4a26-8c1d-578e97365efc: rpi5 | ||
8a67a785-73bb-46d5-b73f-d951a6d3cb43: starlift | ||
issuer: 'https://iam-client-test.us-east.philips-healthsuite.com/authorize/oauth2/v2' | ||
insecureIssuer: 'https://iam-client-test.us-east.philips-healthsuite.com/oauth2/access_token' | ||
saml2LoginURL: 'https://iam-integration.us-east.philips-healthsuite.com/authorize/saml2/login?idp_id=https://sts.windows.net/1a407a2d-7675-4d17-8692-b3ac285306e4/&client_id=sp-philips-hspiam-useast-ct&api-version=1' | ||
clientID: iamclient | ||
clientSecret: SecretHere | ||
iamURL: 'https://iam-client-test.us-east.philips-healthsuite.com' | ||
idmURL: 'https://idm-client-test.us-east.philips-healthsuite.com' | ||
redirectURI: https://dex.hsp.philips.com/callback | ||
getUserInfo: true | ||
userNameKey: sub | ||
scopes: | ||
- auth_iam_introspect | ||
- auth_iam_organization | ||
- openid | ||
- profile | ||
- name | ||
- federated:id | ||
``` | ||
The following fields are supported: | ||
| Config field | Type | Description | | ||
|----------------|-------------|----------------------------------------------------------------------------| | ||
| trustedOrgID | string | The HSP IAM OrgID to determine claims | | ||
| tenantMap | map(string) | Mapping of OrgIDs to tenant IDs (Observability | | ||
| issuer | string | The issuer URL of the HSP IAM deployment | | ||
| insecureIssuer | string | the issuer as returnd by HSP IAM. These are different in current IAM (bug) | | ||
| saml2LoginURL | string | The SAML login URL given by HSP IAM for SSO login (code1) | | ||
| clientID | string | An HSP IAM OAuth2 client ID | | ||
| clientSecret | string | An HSP IAM OAuth2 client secret | | ||
| redirectURI | string | The redirect URI of your Dex deployment. PAth should be `/callback` | | ||
| getUserInfo | bool | Wether to inject complete userInfo as a claim in the JWT Token | | ||
| userNameKey | string | The username key. Should be set to `sub` | | ||
| scopes | string | The scopes to send to HSP IAM | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
package hsdp | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"slices" | ||
"strings" | ||
) | ||
|
||
func (c *HSDPConnector) ExtendPayload(scopes []string, payload []byte, cdata []byte) ([]byte, error) { | ||
var cd ConnectorData | ||
var originalClaims map[string]interface{} | ||
|
||
if err := json.Unmarshal(cdata, &cd); err != nil { | ||
return payload, err | ||
} | ||
if err := json.Unmarshal(payload, &originalClaims); err != nil { | ||
return payload, err | ||
} | ||
|
||
c.logger.Info("ExtendPayload called", "sub", cd.Introspect.Sub, "user", cd.Introspect.Username) | ||
|
||
// Service identity tokens should expire when the service identity token expires | ||
if cd.Introspect.IdentityType == "Service" { | ||
originalClaims["exp"] = cd.Introspect.Expires | ||
originalClaims["username"] = cd.Introspect.Sub | ||
originalClaims["preferred_username"] = cd.Introspect.Sub | ||
} | ||
|
||
for _, scope := range scopes { | ||
// Experimental fill introspect body into claims | ||
if scope == "hsp:iam:introspect" { | ||
originalClaims["intr"] = cd.Introspect | ||
} | ||
// Experimental fill token into claims | ||
if scope == "hsp:iam:token" { | ||
originalClaims["tkn"] = string(cd.AccessToken) | ||
} | ||
} | ||
originalClaims["idt"] = cd.Introspect.IdentityType | ||
// Rewrite subject | ||
var orgSubs []string | ||
var orgGroups []string | ||
var orgRoles []string | ||
for _, org := range cd.Introspect.Organizations.OrganizationList { | ||
for _, role := range org.Roles { | ||
orgRoles = append(orgRoles, fmt.Sprintf("urn:iamr:%s:%s", org.OrganizationID, strings.ToLower(role))) | ||
} | ||
for _, group := range org.Groups { | ||
orgGroups = append(orgGroups, fmt.Sprintf("urn:iamg:%s:%s", org.OrganizationID, strings.ToLower(group))) | ||
} | ||
} | ||
if c.enableRoleClaim && len(orgRoles) > 0 { | ||
originalClaims["roles"] = orgRoles | ||
} | ||
if c.enableGroupClaim && len(orgGroups) > 0 { | ||
originalClaims["groups"] = orgGroups | ||
} | ||
if c.enableRoleClaim && c.roleAsGroupClaim && len(orgRoles) > 0 { | ||
originalClaims["groups"] = orgRoles | ||
delete(originalClaims, "roles") | ||
} | ||
|
||
// Rewrite name | ||
if cd.User.GivenName != "" { | ||
originalClaims["name"] = fmt.Sprintf("%s %s", cd.User.GivenName, cd.User.FamilyName) | ||
} | ||
// Inject username | ||
if cd.Introspect.Username != "" { | ||
originalClaims["username"] = cd.Introspect.Username | ||
originalClaims["preferred_username"] = cd.Introspect.Username | ||
} | ||
if len(orgSubs) > 0 { | ||
subs := strings.Join(orgSubs, ":") | ||
origSub := originalClaims["sub"].(string) | ||
originalClaims["sub"] = fmt.Sprintf("%s:id:%s", subs, origSub) | ||
} | ||
|
||
// Custom claims for Observability | ||
var readTenants []string | ||
// Collect all orgs for which the user has LOG.READ permission | ||
for _, org := range cd.Introspect.Organizations.OrganizationList { | ||
if slices.Contains(org.Permissions, "LOG.READ") { | ||
readTenants = append(readTenants, mapper(org.OrganizationID, c.tenantMap)) | ||
} | ||
} | ||
if len(readTenants) > 0 { | ||
originalClaims["ort"] = readTenants | ||
} | ||
extendedPayload, err := json.Marshal(originalClaims) | ||
if err != nil { | ||
return payload, err | ||
} | ||
return extendedPayload, nil | ||
} | ||
|
||
func mapper(src string, data map[string]string) string { | ||
if orgID, ok := data[src]; ok { | ||
return orgID | ||
} | ||
return src | ||
} |
Oops, something went wrong.