|
1 | | -# ldap-role-manager |
2 | | -LDAP role manager for Casbin |
| 1 | +# LDAP Role Manager |
| 2 | + |
| 3 | +[](https://goreportcard.com/report/github.com/casbin/ldap-role-manager) |
| 4 | +[](https://github.com/casbin/ldap-role-manager/actions/workflows/ci.yml) |
| 5 | +[](https://coveralls.io/github/casbin/ldap-role-manager?branch=master) |
| 6 | +[](https://godoc.org/github.com/casbin/ldap-role-manager) |
| 7 | +[](https://github.com/casbin/ldap-role-manager/releases/latest) |
| 8 | +[](https://discord.gg/S5UjpzGZjN) |
| 9 | + |
| 10 | +LDAP Role Manager is an LDAP-based role manager for [Casbin](https://github.com/casbin/casbin). With this library, Casbin can load role hierarchies and user-role mappings from LDAP directories like Active Directory, OpenLDAP, etc. |
| 11 | + |
| 12 | +## Installation |
| 13 | + |
| 14 | +```bash |
| 15 | +go get github.com/casbin/ldap-role-manager |
| 16 | +``` |
| 17 | + |
| 18 | +## Simple Example |
| 19 | + |
| 20 | +```go |
| 21 | +package main |
| 22 | + |
| 23 | +import ( |
| 24 | + "fmt" |
| 25 | + "log" |
| 26 | + |
| 27 | + "github.com/casbin/casbin/v2" |
| 28 | + ldaprolemanager "github.com/casbin/ldap-role-manager" |
| 29 | +) |
| 30 | + |
| 31 | +func main() { |
| 32 | + // Initialize LDAP role manager |
| 33 | + opts := &ldaprolemanager.LDAPOptions{ |
| 34 | + URL: "ldap://localhost:389", |
| 35 | + BaseDN: "dc=example,dc=com", |
| 36 | + UserFilter: "(uid=%s)", |
| 37 | + GroupFilter: "(member=%s)", |
| 38 | + RoleAttr: "cn", |
| 39 | + BindDN: "cn=admin,dc=example,dc=com", |
| 40 | + BindPassword: "password", |
| 41 | + MaxHierarchyLevel: 10, |
| 42 | + } |
| 43 | + |
| 44 | + rm, err := ldaprolemanager.NewRoleManager(opts) |
| 45 | + if err != nil { |
| 46 | + log.Fatalf("Failed to create role manager: %v", err) |
| 47 | + } |
| 48 | + defer rm.Close() |
| 49 | + |
| 50 | + // Create a new enforcer |
| 51 | + e, err := casbin.NewEnforcer("examples/rbac_model.conf", "examples/rbac_policy.csv") |
| 52 | + if err != nil { |
| 53 | + log.Fatalf("Failed to create enforcer: %v", err) |
| 54 | + } |
| 55 | + |
| 56 | + // Set the role manager |
| 57 | + e.SetRoleManager(rm) |
| 58 | + |
| 59 | + // Load policy |
| 60 | + err = e.LoadPolicy() |
| 61 | + if err != nil { |
| 62 | + log.Fatalf("Failed to load policy: %v", err) |
| 63 | + } |
| 64 | + |
| 65 | + // Check permissions |
| 66 | + if res, _ := e.Enforce("alice", "data1", "read"); res { |
| 67 | + fmt.Println("alice can read data1") |
| 68 | + } else { |
| 69 | + fmt.Println("alice cannot read data1") |
| 70 | + } |
| 71 | +} |
| 72 | +``` |
| 73 | + |
| 74 | +## Configuration Options |
| 75 | + |
| 76 | +The `LDAPOptions` struct supports the following configuration options: |
| 77 | + |
| 78 | +- **URL**: LDAP server URL (e.g., `ldap://localhost:389` or `ldaps://localhost:636`) |
| 79 | +- **BaseDN**: Base distinguished name for searching (e.g., `dc=example,dc=com`) |
| 80 | +- **UserFilter**: LDAP filter template for finding users (e.g., `(uid=%s)`) |
| 81 | +- **GroupFilter**: LDAP filter template for finding groups (e.g., `(member=%s)`) |
| 82 | +- **RoleAttr**: Attribute name containing role/group names (default: `cn`) |
| 83 | +- **BindDN**: Distinguished name for binding to LDAP (optional) |
| 84 | +- **BindPassword**: Password for binding to LDAP (optional) |
| 85 | +- **UseTLS**: Enable TLS connection (default: `false`) |
| 86 | +- **SkipTLSVerify**: Skip TLS certificate verification (default: `false`) |
| 87 | +- **MaxHierarchyLevel**: Maximum depth for role hierarchy traversal (default: `10`) |
| 88 | + |
| 89 | +## LDAP Schema Requirements |
| 90 | + |
| 91 | +This role manager expects the following LDAP schema: |
| 92 | + |
| 93 | +### User Entries |
| 94 | +- Users should be identifiable by the `UserFilter` (e.g., `uid` attribute) |
| 95 | +- Example: `uid=alice,ou=users,dc=example,dc=com` |
| 96 | + |
| 97 | +### Group Entries |
| 98 | +- Groups should contain a `member` attribute listing user DNs |
| 99 | +- Groups should have a role name attribute (configured via `RoleAttr`, default is `cn`) |
| 100 | +- Example: `cn=admin,ou=groups,dc=example,dc=com` |
| 101 | + |
| 102 | +### Example LDIF |
| 103 | + |
| 104 | +```ldif |
| 105 | +# User entry |
| 106 | +dn: uid=alice,ou=users,dc=example,dc=com |
| 107 | +objectClass: inetOrgPerson |
| 108 | +uid: alice |
| 109 | +cn: Alice Smith |
| 110 | +sn: Smith |
| 111 | +
|
| 112 | +# Group entry |
| 113 | +dn: cn=admin,ou=groups,dc=example,dc=com |
| 114 | +objectClass: groupOfNames |
| 115 | +cn: admin |
| 116 | +member: uid=alice,ou=users,dc=example,dc=com |
| 117 | +``` |
| 118 | + |
| 119 | +## Active Directory Example |
| 120 | + |
| 121 | +For Active Directory, you might use different filters: |
| 122 | + |
| 123 | +```go |
| 124 | +opts := &ldaprolemanager.LDAPOptions{ |
| 125 | + URL: "ldaps://ad.example.com:636", |
| 126 | + BaseDN: "dc=example,dc=com", |
| 127 | + UserFilter: "(sAMAccountName=%s)", |
| 128 | + GroupFilter: "(member=%s)", |
| 129 | + RoleAttr: "cn", |
| 130 | + BindDN: "cn=service-account,ou=users,dc=example,dc=com", |
| 131 | + BindPassword: "password", |
| 132 | + UseTLS: true, |
| 133 | +} |
| 134 | +``` |
| 135 | + |
| 136 | +## Features |
| 137 | + |
| 138 | +- **Read-only Role Management**: Roles are managed in LDAP, not in Casbin policies |
| 139 | +- **Role Hierarchy Support**: Supports nested group memberships up to `MaxHierarchyLevel` |
| 140 | +- **Multiple Group Membership**: Users can belong to multiple groups/roles |
| 141 | +- **Flexible LDAP Schema**: Configurable filters and attributes to match your LDAP schema |
| 142 | +- **TLS Support**: Secure connections to LDAP servers |
| 143 | +- **Thread-safe**: Safe for concurrent use |
| 144 | + |
| 145 | +## API |
| 146 | + |
| 147 | +The LDAP Role Manager implements the `rbac.RoleManager` interface: |
| 148 | + |
| 149 | +- `GetRoles(name string, domain ...string) ([]string, error)` - Get roles for a user |
| 150 | +- `GetUsers(roleName string, domain ...string) ([]string, error)` - Get users with a specific role |
| 151 | +- `HasLink(name1 string, name2 string, domain ...string) (bool, error)` - Check if a user has a role |
| 152 | +- `GetImplicitRoles(name string, domain ...string) ([]string, error)` - Get all roles including nested ones |
| 153 | +- `GetImplicitUsers(roleName string, domain ...string) ([]string, error)` - Get all users with a role |
| 154 | + |
| 155 | +Note: Methods like `AddLink` and `DeleteLink` are no-ops since roles are managed in LDAP. |
| 156 | + |
| 157 | +## Testing |
| 158 | + |
| 159 | +Run the tests with: |
| 160 | + |
| 161 | +```bash |
| 162 | +go test -v ./... |
| 163 | +``` |
| 164 | + |
| 165 | +For tests with coverage: |
| 166 | + |
| 167 | +```bash |
| 168 | +go test -v -coverprofile=coverage.out ./... |
| 169 | +go tool cover -html=coverage.out |
| 170 | +``` |
| 171 | + |
| 172 | +## Related Projects |
| 173 | + |
| 174 | +- [Casbin](https://github.com/casbin/casbin) - Authorization library |
| 175 | +- [Gorm Adapter](https://github.com/casbin/gorm-adapter) - Casbin adapter for GORM |
| 176 | +- [Redis Watcher](https://github.com/casbin/redis-watcher) - Redis watcher for Casbin |
| 177 | +- [Etcd Watcher](https://github.com/casbin/etcd-watcher) - Etcd watcher for Casbin |
| 178 | + |
| 179 | +## Getting Help |
| 180 | + |
| 181 | +- [Casbin Documentation](https://casbin.org/) |
| 182 | +- [GitHub Issues](https://github.com/casbin/ldap-role-manager/issues) |
| 183 | +- [Discord](https://discord.gg/S5UjpzGZjN) |
| 184 | + |
| 185 | +## License |
| 186 | + |
| 187 | +This project is licensed under the Apache License 2.0. See the [LICENSE](LICENSE) file for the full license text. |
0 commit comments