Skip to content
This repository has been archived by the owner on Mar 2, 2024. It is now read-only.

Commit

Permalink
Update examples (#24)
Browse files Browse the repository at this point in the history
* Update location to basePath
appgateway.location property has been deprecated in favor of basePath

* Update extensions path to match our docs.strata.io

* Update allowUnauthenticated regex

The intent of this policy is to allow resources such as favicon.ico to be
proxied without authentication required. However, the previous regex also
matched resources such as 'resource.jpg.txt'.

The updated regex will ensure that the extensions are at the end of the
resource path.

* Adds .idea to .gitignore

* Remove unnecessary idps block

* Add LDAP search example (#25)

Signed-off-by: Warren Fernandes <[email protected]>
  • Loading branch information
wfernandes authored Jun 23, 2023
1 parent 9ac8304 commit 5953474
Show file tree
Hide file tree
Showing 8 changed files with 300 additions and 19 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
.DS_Store
.idea
17 changes: 7 additions & 10 deletions header-creation/maverics.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,24 @@ http:

appgateways:
- name: exampleHeaderCreation
location: /
basePath: /
# The 'upstream' used here is purely for demonstration and can be replaced with
# any URL that is resolvable from the machine the Orchestrator is running on.
upstream: https://httpbin.org

headers:
EXAMPLE-SUB: azure.sub
# It is assumed the header.go Service Extension file resides in the
# '/etc/maverics' directory. To change that, update the 'file' fields below.
# '/etc/maverics/extensions' directory. To change that, update the 'file' fields below.
# TODO: confirm the file paths defined below are correct.
EXAMPLE-FIRST-NAME:
createHeader:
funcName: CreateFirstNameHeader
file: /etc/maverics/header.go
file: /etc/maverics/extensions/header.go
EXAMPLE-LAST-NAME:
createHeader:
funcName: CreateLastNameHeader
file: /etc/maverics/header.go
file: /etc/maverics/extensions/header.go

policies:
- location: /
Expand All @@ -39,13 +39,10 @@ appgateways:
authorization:
allowAll: true

# Azure AD is used as the IDP in this example, but that can easily be changed by
# modifying the IDP and connector definitions below. For more info on connectors,
# please reference https://docs.strata.io/get-acquainted/connectors.
idps:
- name: azure

connectors:
# Azure AD is used as the IDP in this example, but that can easily be changed by
# modifying the IDP and connector definitions below. For more info on connectors,
# please reference https://docs.strata.io/get-acquainted/connectors.
- name: azure
type: azure
authType: oidc
Expand Down
14 changes: 5 additions & 9 deletions idp-selector/maverics.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ http:

appgateways:
- name: headers
location: /
basePath: /
# The 'upstream' used here is purely for demonstration and can be replaced with
# any URL that is resolvable from the machine the Orchestrator is running on.
upstream: https://httpbin.org
Expand All @@ -21,26 +21,22 @@ appgateways:
- location: /
authentication:
# It is assumed the auth.go Service Extension file resides in the
# '/etc/maverics' directory. To change that, update the 'file' fields below.
# '/etc/maverics/extensions' directory. To change that, update the 'file' fields below.
isAuthenticatedSE:
funcName: IsAuthenticated
file: /etc/maverics/auth.go
file: /etc/maverics/extensions/auth.go
authenticateSE:
funcName: Authenticate
file: /etc/maverics/auth.go
file: /etc/maverics/extensions/auth.go
authorization:
allowAll: true

- location: ~ \.(jpg|png|ico|svg|ttf|js|css)
- location: ~ \.(jpg|png|ico|svg|ttf|js|css)$
authentication:
allowUnauthenticated: true
authorization:
allowAll: true

idps:
- name: azure
- name: auth0

connectors:
# The 'name' property is used as a unique ID that the Service Extensions depend on.
# Please ensure the Service Extensions are updated if the name of the connectors change.
Expand Down
33 changes: 33 additions & 0 deletions ldap-search/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# LDAP Search Service Extension

There are times when you may find the need to construct a unique LDAP search
query that isn't easily available via the LDAP connector. For example,
returning multiple result entries.

This example will show you how to query LDAP securely by upgrading the TCP
connection to TLS and then make a request to the LDAP server to retrieve groups
with a specific `uniqueMember` attribute.

The structure of the LDAP can be seen in the [`example.ldif`](./example.ldif) file.

For more information regarding the `maverics/ldap` pkg, please refer to
the [Service Extension Maverics package documentation][maverics-ldap-docs].

## Setup

Please reference the [maverics.yaml](maverics.yaml) configuration file and the
Service Extension files it references for a set action items specified with`TODO`.
These action items are changes necessary to get this example running.

## Testing

1. Complete all the action items specified by `TODO`s
1. Restart the Orchestrator, and ensure it starts successfully.
1. Navigate to the URL the Orchestrator is listening on in your browser:
e.g. https://localhost/headers.
1. You should now be redirected your specified IDP and prompted for authentication.
1. After successfully logging in, the custom headers that were created will be sent
to the upstream application. This can be confirmed by verifying the
`EXAMPLE-GROUPS` header is rendered on the `/headers` page of the sample app.

[maverics-ldap-docs]: https://docs.strata.io/orchestrator-reference/service-extensions/maverics-packages#package-maverics-ldap
75 changes: 75 additions & 0 deletions ldap-search/example.ldif
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
version: 1

dn: dc=examples,dc=com
objectClass: dcObject
objectClass: organization
objectClass: top
dc: examples
o: Example Org

dn: ou=People,dc=examples,dc=com
objectClass: organizationalUnit
ou: People

dn: uid=state,ou=People,dc=examples,dc=com
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: top
cn: Samuel Tate
sn: Tate
givenName: Samuel
mail: [email protected]
mobile: 604-555-5555
uid: state
userPassword:: d9TEVvbr3a#LeUc$p

dn: uid=aadkins,ou=People,dc=examples,dc=com
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: top
cn: Allan Adkins
sn: Adkins
givenName: Allan
mail: [email protected]
mobile: 604-555-9090
uid: aadkins
userPassword:: d9TEVvbr3a#LeUc$p

dn: uid=shiggins,ou=People,dc=examples,dc=com
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: top
cn: Shelly Higgins
sn: Higgins
givenName: Shelly
mail: [email protected]
mobile: 415-123-4567
uid: shiggins
userPassword:: d9TEVvbr3a#LeUc$p

dn: ou=groups,dc=examples,dc=com
objectClass: organizationalUnit
objectClass: top
ou: groups

dn: cn=GroupOne,ou=groups,dc=examples,dc=com
objectClass: groupOfUniqueNames
objectClass: top
cn: GroupOne
uniqueMember: [email protected],ou=People,dc=examples,dc=com

dn: cn=GroupTwo,ou=groups,dc=examples,dc=com
objectClass: groupOfUniqueNames
objectClass: top
cn: GroupTwo
uniqueMember: [email protected],ou=People,dc=examples,dc=com

dn: cn=GroupThree,ou=groups,dc=examples,dc=com
objectClass: groupOfUniqueNames
objectClass: top
cn: GroupThree
uniqueMember: [email protected],ou=People,dc=examples,dc=com

114 changes: 114 additions & 0 deletions ldap-search/loadAttrs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package main

import (
"crypto/tls"
"crypto/x509"
"errors"
"fmt"
"net/http"
"strings"

"maverics/app"
"maverics/ldap"
"maverics/log"
"maverics/secret"
"maverics/session"
)

const (
// TODO: Adjust these values based on your LDAP configuration.
ldapServerName = "ldap.examples.com"
ldapBaseDN = "dc=examples,dc=com"
ldapFilterFmt = "(&(uniquemember=uid=%s,ou=People,dc=examples,dc=com))"

delimiter = ","
)

// LoadAttrs loads attributes from LDAP and then stores them on the session for later
// use.
func LoadAttrs(_ *app.AppGateway, _ http.ResponseWriter, req *http.Request) error {
log.Debug("se", "loading attributes from LDAP")

uid := session.GetString(req, "azure.email")
if uid == "" {
return fmt.Errorf("unable to get uid from session")
}
filter := fmt.Sprintf(ldapFilterFmt, uid)
groupsMap, err := getGroups(ldapBaseDN, filter)
if err != nil {
log.Error("se", "unable to get groups", "error", err.Error())
return err
}

groups := make([]string, 0, len(groupsMap))
for k, _ := range groupsMap {
groups = append(groups, k)
}

list := strings.Join(groups, delimiter)
log.Debug(
"se", "setting groups attribute on session",
"se.groups", list,
)

session.Set(req, "se.groups", list)

return nil
}

// getGroups will search the LDAP ldapBaseDN using the provided filter and return a
// list of unique groups.
func getGroups(baseDN, filter string) (map[string]struct{}, error) {
ldapURL := fmt.Sprintf("ldap://%s", ldapServerName)
log.Info("se", "dialing to ldap over tcp", "url", ldapURL)
conn, err := ldap.DialURL(ldapURL)
if err != nil {
return nil, fmt.Errorf("unable to dial ldap: %w", err)
}
defer conn.Close()

caCert := secret.GetString("ldapCACert")
certPool, err := x509.SystemCertPool()
if err != nil {
return nil, fmt.Errorf("unable to get system cert pool: %w", err)
}
ok := certPool.AppendCertsFromPEM([]byte(caCert))
if !ok {
return nil, errors.New("unable to append ca cert to pool")
}
err = conn.StartTLS(&tls.Config{
RootCAs: certPool,
ServerName: ldapServerName,
})
if err != nil {
return nil, fmt.Errorf("unable to start tls: %w", err)
}

serviceAccountUsername := secret.GetString("serviceAccountUsername")
serviceAccountPassword := secret.GetString("serviceAccountPassword")
err = conn.Bind(serviceAccountUsername, serviceAccountPassword)
if err != nil {
return nil, fmt.Errorf("unable to bind ldap: %w", err)
}

searchReq := ldap.NewSearchRequest(
baseDN, // The base dn to search
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
filter, // The filter to apply
[]string{"cn"}, // A list attributes to retrieve
nil,
)
searchResult, err := conn.Search(searchReq)
if err != nil {
return nil, fmt.Errorf("unable to search ldap: %w", err)
}

groups := make(map[string]struct{})
for _, entry := range searchResult.Entries {
groups[entry.GetAttributeValue("cn")] = struct{}{}

fmt.Printf("%s: %v\n", entry.DN, entry.GetAttributeValue("cn"))
}

return groups, nil
}
57 changes: 57 additions & 0 deletions ldap-search/maverics.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
version: ldap-search-loadAttrs

tls:
maverics:
# TODO: replace the 'certFile' and 'keyFile' values with an absolute path to a
# certificate pair. For more info on the TLS configuration, please reference
# https://scriptum.strata.io/get-started/transport-security.
certFile: { ABSOLUTE PATH TO CERT FILE }
keyFile: { ABSOLUTE PATH TO KEY FILE }

http:
address: ":443"
tls: maverics

logger:
level: debug

appgateways:
- name: exampleLDAPSearchLoadAttrs
basePath: /
# The 'upstream' used here is purely for demonstration and can be replaced with
# any URL that is resolvable from the machine the Orchestrator is running on.
upstream: https://cylog.org
headers:
EXAMPLE-GROUPS: se.groups

loadAttrsSE:
# It is assumed the loadAttrs.go Service Extension file resides in the
# '/etc/maverics/extensions' directory. To change that, update the 'file' field below.
funcName: LoadAttrs
file: /etc/maverics/extensions/loadAttrs.go

policies:
- location: ~ \.(jpg|png|ico|svg|ttf|js|css|gif)$
authentication:
allowUnauthenticated: true
authorization:
allowAll: true
- location: /
authentication:
idps:
- azure
authorization:
allowAll: true

connectors:
# The 'name' property is used as a unique ID that the Service Extensions depend on.
# Please ensure the Service Extensions are updated if the name of the connectors change.
# Additionally, please note that the 'oauthRedirectURL' used in the two connectors
# must be unique.
- name: azure
type: azure
authType: saml
# TODO: Configure the SAML Azure IDP.
samlMetadataURL: { SAML METADATA URL }
samlConsumerServiceURL: { SAML CONSUMER SERVICE URL }
samlEntityID: { SAML ENTITY ID }
8 changes: 8 additions & 0 deletions ldap-search/secrets.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
secrets:
serviceAccountUsername: cn=service,dc=examples,dc=com
serviceAccountPassword: uCgfpeeyGk9Vgf$*$
ldapCACert: |+
-----BEGIN CERTIFICATE-----
TODO: Add LDAP CA Cert.
-----END CERTIFICATE-----

0 comments on commit 5953474

Please sign in to comment.