FreeRadius 3.0.1 Unlang Policy to Dynamically match User -> Client -> LDAP group - freeradius

I have my Radius working with AD + Google OTP working fine. What I am trying to accomplish now is to specify user-to-client-to-ADgroup in a policy and/or unlang within the post-auth.
How it works today:
client performs request
Radius sends first half of the password to AD
Radius sends the second half of the password to Google OTP
If both come back good, then auth is successful
Post-auth does some checking if user is memberof ADgroup -> assign
class -> accept
OR if not part of ADgroup -> reject
The part I need assistance with is I have over 30 sites with equipment in each one. We distinguish our users based on per site access. E.g. NetworkAdmin01 is allowed to access site01 but not site02.
So the only way I can think of doing this:
Each site has it's own virtual server (VS)
Each client has the "virtual server" attribute set
Within each VS there is post-auth unlang like:
if (LDAP-Group == "NetworkAdmins_site01") {
[do something] (update control, update reply, etc..)
else
reject
This setup would require me to have 30+ VS running on the Radius and is not manageable.
If I was able to run this within a few VS (separated based on equipment vendor)Want within the post-auth to grant/assign based on;
if (%{client:shortname} =~ /regex/) #grab the portion of the variable between "." (site01)
if (LDAP-Group =~ /regex/) # grab the portion of the variable after last "_" (site01)
if (%{0} == %{1}) {
if (LDAP-Group == NetworkAdmins_site01) {
update reply {
Juniper-Local-User-Name := "admins_group"
}
}
else {
update control {
Auth-type := "Reject"
}
}
}
}
}

So after a lot of looking around, it appears that runtime dynamic variables are the biggest limitation to building any type of policies/rules.
so I went a different direction. I have basically matched the NAS-IP-Address to the IP subnet/site I expect the request to come from.
So this is placed into the Post-Auth section of each VS. Not the most manageable way when you have 30+ sites but, best I could find at this point (without running 30+ VS).
# SITE01 site
if (&NAS-IP-Address < 10.1.0.0/16) {
if (LDAP-Group == "Radius_NetworkAdmins_SITE01") {
update reply {
Juniper-Local-User-Name := "ad-super-users"
}
}
elsif (LDAP-Group == "Radius_NetworkAdminsRO_SITE01") {
update reply {
Juniper-Local-User-Name := "ad-readonly-users"
}
}
}
# SITE02 site
if (&NAS-IP-Address < 10.2.0.0/16) {
if (LDAP-Group == "Radius_NetworkAdmins_SITE02") {
update reply {
Juniper-Local-User-Name := "ad-super-users"
}
}
elsif (LDAP-Group == "SG_Uni_Radius_NetworkAdminsRO_SITE02") {
update reply {
Juniper-Local-User-Name := "ad-readonly-users"
}
}
}
else {
update reply {
Reply-Message := "Not authorized to access this system"
}
update control {
Auth-Type := "Reject"
}
}
#
Post-Auth-Type REJECT {
-sql
attr_filter.access_reject
eap
remove_reply_message_if_eap
}
}
Post-Auth-Type Challenge {
}
#
pre-proxy {
}
#
post-proxy {
eap
}

Related

How to expose only some routes depending on host

I have a Vapor app that needs to do most things authenticated via HTTPS, but also needs to receive unauthenticated PUT requests via HTTP.
Can I conditionalize my route definitions based on the server's host name or authentication type? How can I capture that information from the server?
If you start up the different instances of vapor using the command line argument --hostname, you can put this code in your configure.swift and then include different routes as needed per host. You will then get 404s if invalid routes are attempted on the wrong hosts.
if let index = env.arguments.index(of: "--hostname")
{
if env.arguments.count > index
{
let hostname = env.arguments[index+1]
if hostname == "hostA"
{
// load routes
}
else
{
// load other routes
}
}
}
An alternative is to use custom Middleware. Something like this enables the hostname being called in the request to be inspected and prohibited routes can be re-directed:
struct HostSpecificMiddleware:Middleware
{
func respond( to request: Request, chainingTo next: Responder ) throws -> Future<Response>
{
let host = request.http.headers.filter{ (arg) in let (name, _) = arg; return name == "Host" }[0]
if host.1 == "hostA:8080"
{
if request.http.url.path == "routeA"
{
throw Abort.redirect(to:"routeNotAllowed")
}
}
return try next.respond(to: request)
}
}
You can then configure the middleware into routes in configure.swift using:
let soMW = HostSpecificMiddleware()
let users = router.grouped(uriUsers).grouped(soMW)
The second approach gives you much more flexibility.

grails application access after authentication with ldap role based authorization

Our grails application uses ldap authentication, without any problems, now I need to prevent access, to the entire application, if a user has no specific ldap role.
I can see the role and use it in my Config.groovy annotations or secure the actions in the controllers, but instead I need a scenario/way to just show a "Denied ..." message and logout. (POST Forbidden 403).
def filters = {
loginFilter(controller:'login', action:'ajaxSuccessSproutcore') {
before = {
switch(Environment.current.name) {
case { it == 'development' || it == 'hrm'}:
if (springSecurityService.isLoggedIn() && grails.plugin.springsecurity.SpringSecurityUtils.ifAnyGranted("ROLE_ADMIN, ROLE_SEA_HRM_LOGIN")){
} else {
if (springSecurityService.isLoggedIn()) {
render ([msg:''] as JSON)
session.invalidate()
return false
}
}
break
default:
if (springSecurityService.isLoggedIn() && grails.plugin.springsecurity.SpringSecurityUtils.ifAnyGranted("ROLE_ADMIN , ROLE_USER")){
} else {
if (springSecurityService.isLoggedIn()) {
render ([msg:''] as JSON)
session.invalidate()
return false
}
}
break
}
}
after = { Map model ->
}
afterView = { Exception e ->
}
}
}
In grails 3 you can set up an Interceptor to check every request and take the appropriate action. In your case you'd want to add a check in the before block.
Edit: As Jeff Brown notes in the comments, grails 2 used Filters rather than interceptors.
Edit: Something like this in your logout logic:
...
else {
if (springSecurityService.isLoggedIn()) {
session.invalidate()
redirect action:'youShallNotPass'
return false
}
}

Can admin role get other users permissions in Spring-security ACL Grails

I am trying to make a proof of concept application that allows the user with administration permission to grant and revoke permissions of other users. While granting and revoking works with only username (unique identifier) getting the permission to display in the UI proves to be out of my reach. Is it possible to get a list of other user's permissions from within a service method?
I've tried to search the web but I couldn't find any solution that would apply to my problem. I have tried using SwitchUserAuthorityChanger, RunAsManager and aclService.readAclsById. None of those worked.
I am using Grails 3.3.2 with Spring-Security 3.2.0 and ACL 3.2.0.
Cheers folks!
I ended up solving this myself. I'll post the answer here in case some poor soul would run into a similar problem.
After digging a bit in the ACL database tables, I created a separate service in which I get AclObjectIdentity by its id, I get users sid. Using these variables I find all related variables from AclEntry. After that its just a matter of getting permissions by their mask.
Here is the method in case it might help anyone:
def getPermissions(Object domainObject, String sid) {
Map<String, String> returnValue = [
"status": "success"
]
def aclObject = AclObjectIdentity.findByObjectId(domainObject.id)
def userAclSid = AclSid.findBySid(sid)
if (null == userAclSid || null == aclObject) {
returnValue["status"] = "failed"
return returnValue
}
def aclEntries = AclEntry.findAllBySidAndAclObjectIdentity(userAclSid, aclObject)
returnValue["permissions"] = []
def tempMap = [:]
if (null == aclEntries) {
returnValue["permissions"] = "null"
return returnValue
}
def counter = 0
for (entry in aclEntries) {
int mask = entry.mask
BasePermission permission
for (BasePermission perm in PermissionEnum.toList()) {
int test = 1 << mask
if (perm.getMask() == test) {
permission = perm
break;
}
}
def permString = PermissionEnum.getPermission(permission)
tempMap["$counter"] = permString
counter++
}
returnValue["permissions"] = tempMap
return returnValue
}

freeradius prevent user to login to some devices

How can I prevent some user to login to some network devices on freeradius server? I've created policy:
deny_beli {
if (User-Name == "belitest") {
reject
}
}
But I need only to ban login to network devices on subnet 172.0.0.0/23, not others. Thanks.
I changed policy:
deny_beli {
if (User-Name == "belitest") {
if(NAS-IP-Address =~ /172.0.0./){
reject
}
if(NAS-IP-Address =~ /172.0.1./){
reject
}
}
}
Now, everything is working smoothly.

Grails channel security causing a redirect loop

I am new to Grails and I am working on an exisiting application. I am trying to force the anyone using our website to allways be on https. I added the Spring Security Core plugin
//BuildConfig.groovy
compile "org.grails.plugins:spring-security-core:2.0.0"
and I just added
///Config.groovy
grails.plugin.springsecurity.secureChannel.definition = [
'/**': 'REQUIRES_SECURE_CHANNEL'
When I try to go on localhost:8080/myapp, it redirects me to https://localhost:8443/myapp, but I get a "This webpage has a redirect loop ERR_TOO_MANY_REDIRECTS" message.
I added print statements in my SecurityFilters.groovy, and I can see the infinite loop going
baseFilter(controller: "*", action: "*")
{
before = {
println "baseFilter"
// If auth controller then ok to continue
if (controllerName.equals("auth"))
{
return true;
}
// If no subject (user) and not auth controller then user must authenticate
if (!session.subject && !(controllerName.equals("auth")))
{
params.targetUri = request.forwardURI - request.contextPath
if (params.action=="profile") {
params.targetUri=params.targetUri + "?page=" + params?.page
}
else if (params.action=="results") {
params.targetUri="/home"
}
println "baseFilter: Redirecting: PARAMS = $params"
redirect(controller:'auth', action:'login', params: params)
return false;
}
}
}
It's just:
baseFilter
baseFilter: Redirecting: PARAMS = [action:auth, format:null, controller:login, targetUri:/login/auth]
Over and over.
I've tried many other things I found on Stackoverflow and other websites, but they either do not work, or are too complicated.
Thank you.
Ok, so this isn't the answer to the question, but I managed to achieve what I was trying to do, which was to force SLL, and redirect any attempts to use http. I did this by using the shiro plugin, which was already being used by my application. In the Buildconfig.groovy, just add compile ":shiro:1.2.1" to you plugins. In the config.groovy I added the following properties:
security {
shiro {
filter {
loginUrl = "/login"
successUrl = "/"
unauthorizedUrl = "/unauthorized"
filterChainDefinitions = """
/** = ssl[443]
"""
}
}
}
You can modify your filterChainDefinitions to only force ssl on certain urls. I just used /** because I always want SSL.

Resources