Skip to content

Commit

Permalink
refactored code to add admin to user account based on group membershi…
Browse files Browse the repository at this point in the history
…p each login (issue #109); added groups claim value to OD record on each login in _xcreds_oidc_groups (issue #117)
  • Loading branch information
twocanoes committed Nov 29, 2023
1 parent 6f37372 commit 8376942
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 82 deletions.
23 changes: 23 additions & 0 deletions NomadLogin/DSQueryable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,29 @@ public extension DSQueryable {

}

func makeAdmin(_ user:ODRecord) -> Bool {
do {
os_log("Find the administrators group", type: .debug)
let query = try ODQuery.init(node: localNode,
forRecordTypes: kODRecordTypeGroups,
attribute: kODAttributeTypeRecordName,
matchType: ODMatchType(kODMatchEqualTo),
queryValues: "admin",
returnAttributes: kODAttributeTypeNativeOnly,
maximumResults: 1)
let results = try query.resultsAllowingPartial(false) as! [ODRecord]
let adminGroup = results.first

os_log("Adding user to administrators group", type: .debug)
try adminGroup?.addMemberRecord(user)

} catch {
let errorText = error.localizedDescription
os_log("Unable to add user to administrators group: %{public}@", type: .error, errorText)
return false
}
return true
}
func getAllStandardUsers() throws -> [ODRecord] {
let allRecords = try getAllNonSystemUsers()
let nonSystem = allRecords.filter { (record) -> Bool in
Expand Down
20 changes: 11 additions & 9 deletions XCredsLoginPlugIn/LoginWindow/LoginWebViewWindowController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,17 @@ class LoginWebViewWindowController: WebViewWindowController, DSQueryable {
return
}

//groups
if let mapValue = idTokenInfo["groups"] as? Array<String> {
TCSLogWithMark("setting groups: \(mapValue)")
delegate.setHint(type: .groups, hint:mapValue)
}
else {

TCSLogWithMark("No groups found")
}


guard let subValue = idTokenInfo["sub"] as? String, let issuerValue = idTokenInfo["iss"] as? String else {
delegate.denyLogin(message:"OIDC token does not contain both a sub and iss value.")
return
Expand Down Expand Up @@ -408,15 +419,6 @@ class LoginWebViewWindowController: WebViewWindowController, DSQueryable {
delegate.setHint(type: .fullName, hint: "\(firstName) \(lastName)")

}
//groups
if let mapValue = idTokenInfo["groups"] as? Array<String> {
TCSLogWithMark("setting groups: \(mapValue)")
delegate.setHint(type: .groups, hint:mapValue)
}
else {

TCSLogWithMark("No groups found")
}

//first name
if let mapKey = DefaultsOverride.standardOverride.object(forKey: "map_firstname") as? String, mapKey.count>0, let mapValue = idTokenInfo[mapKey] as? String {
Expand Down
6 changes: 5 additions & 1 deletion XCredsLoginPlugIn/Mechanisms/XCredsBaseMechanism.swift
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ protocol XCredsMechanismProtocol {

return true
}
class func updateOIDCInfo(user: String, iss:String?, sub:String? ) -> Bool {
class func updateOIDCInfo(user: String, iss:String?, sub:String?, groups:[String]?) -> Bool {
os_log("Checking for local username", log: noLoMechlog, type: .default)
var records = [ODRecord]()
let odsession = ODSession.default()
Expand Down Expand Up @@ -308,6 +308,10 @@ protocol XCredsMechanismProtocol {
try records.first?.setValue(iss, forAttribute: "dsAttrTypeNative:_xcreds_oidc_iss")


if let groups = groups?.joined(separator: ";") {
try records.first?.setValue(groups, forAttribute: "dsAttrTypeNative:_xcreds_oidc_groups")

}
} catch {
os_log("Unable to add OIDC Info", log: noLoMechlog, type: .error)
return false
Expand Down
119 changes: 61 additions & 58 deletions XCredsLoginPlugIn/Mechanisms/XCredsCreateUser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import OpenDirectory


/// Mechanism to create a local user and homefolder.
class XCredsCreateUser: XCredsBaseMechanism {
class XCredsCreateUser: XCredsBaseMechanism, DSQueryable {

let createUserLog = "createUserLog"
let uiLog = "uiLog"
Expand Down Expand Up @@ -69,7 +69,23 @@ class XCredsCreateUser: XCredsBaseMechanism {
}
}
}

var isAdmin = false
if let createAdmin = getManagedPreference(key: .CreateAdminUser) as? Bool {
isAdmin = createAdmin
TCSLog("Found a createLocalAdmin key value: \(isAdmin.description)")
}
os_log("Checking for CreateAdminIfGroupMember groups", log: uiLog, type: .debug)
if let adminGroups = getManagedPreference(key: .CreateAdminIfGroupMember) as? [String] {
TCSLogWithMark("Found a CreateAdminIfGroupMember key value: \(String(describing: groups))")
groups?.forEach { group in
if adminGroups.contains(group) {
isAdmin = true
TCSLogWithMark("User is a member of \(group) group. Setting isAdmin = true ")
}
}
}


if let xcredsPass=xcredsPass,let xcredsUser = xcredsUser, XCredsCreateUser.checkForLocalUser(name: xcredsUser)==false{

var secureTokenCreds:SecureTokenCredential? = nil
Expand All @@ -90,28 +106,13 @@ class XCredsCreateUser: XCredsBaseMechanism {
}

TCSLog("Checking for createLocalAdmin key")
var isAdmin = false
if let createAdmin = getManagedPreference(key: .CreateAdminUser) as? Bool {
isAdmin = createAdmin
TCSLog("Found a createLocalAdmin key value: \(isAdmin.description)")
}
os_log("Checking for CreateAdminIfGroupMember groups", log: uiLog, type: .debug)
if let adminGroups = getManagedPreference(key: .CreateAdminIfGroupMember) as? [String] {
TCSLogWithMark("Found a CreateAdminIfGroupMember key value: \(String(describing: groups))")
groups?.forEach { group in
if adminGroups.contains(group) {
isAdmin = true
TCSLogWithMark("User is a member of \(group) group. Setting isAdmin = true ")
}
}
}

var fullname:String?

if let fullnameHint = getHint(type: .fullName) as? String {
fullname=fullnameHint
}


var customAttributes = [String: String]()

let metaPrefix = "_xcreds"
Expand Down Expand Up @@ -198,29 +199,47 @@ class XCredsCreateUser: XCredsBaseMechanism {
os_log("Skipping local account creation", log: createUserLog, type: .default)
}

var sub:String?
var iss:String?
var alias:String?
if let oidcSubHint = getHint(type: .oidcSub) as? String {
sub=oidcSubHint
}
if let oidcIssHint = getHint(type: .oidcIssuer) as? String {
iss=oidcIssHint
}
if let aliasHint = getHint(type: .aliasName) as? String {
alias=aliasHint
}
// Set the xcreds attributes to stamp this account as the mapped one
setTimestampFor(xcredsUser ?? "")
if let iss = iss, let sub = sub {
updateOIDCInfo(xcredsUser ?? "", iss: iss, sub:sub)
}

var sub:String?
var iss:String?
var alias:String?
if let oidcSubHint = getHint(type: .oidcSub) as? String {
sub=oidcSubHint
}
if let oidcIssHint = getHint(type: .oidcIssuer) as? String {
iss=oidcIssHint
}
if let aliasHint = getHint(type: .aliasName) as? String {
alias=aliasHint
}
// Set the xcreds attributes to stamp this account as the mapped one
setTimestampFor(xcredsUser ?? "")
if let iss = iss, let sub = sub {
updateOIDCInfo(xcredsUser ?? "", iss: iss, sub:sub, groups:groups)
}
if let alias = alias, let xcredsUser = xcredsUser {
if XCredsCreateUser.addAlias(name: xcredsUser, alias: alias)==false {
os_log("error adding alias", log: createUserLog, type: .debug)
}
if let alias = alias, let xcredsUser = xcredsUser {
if XCredsCreateUser.addAlias(name: xcredsUser, alias: alias)==false {
os_log("error adding alias", log: createUserLog, type: .debug)
}
TCSLogWithMark("Checking if user should be made admin")
if isAdmin==true, let xcredsUser = xcredsUser {
do {
TCSLogWithMark("Making admin user")
let record = try getLocalRecord(xcredsUser)
if makeAdmin(record)==false {
os_log("failed to make user an admin", log: createUserLog, type: .error)
}
}
catch {
os_log("error finding user to make admin", log: createUserLog, type: .error)
}

}



os_log("Allowing login", log: createUserLog, type: .debug)
let _ = allowLogin()
os_log("CreateUser mech complete", log: createUserLog, type: .debug)
Expand Down Expand Up @@ -372,26 +391,10 @@ class XCredsCreateUser: XCredsBaseMechanism {
}
}

if isAdmin {
do {
os_log("Find the administrators group", log: createUserLog, type: .debug)
let node = try ODNode.init(session: session, type: ODNodeType(kODNodeTypeLocalNodes))
let query = try ODQuery.init(node: node,
forRecordTypes: kODRecordTypeGroups,
attribute: kODAttributeTypeRecordName,
matchType: ODMatchType(kODMatchEqualTo),
queryValues: "admin",
returnAttributes: kODAttributeTypeNativeOnly,
maximumResults: 1)
let results = try query.resultsAllowingPartial(false) as! [ODRecord]
let adminGroup = results.first

os_log("Adding user to administrators group", log: createUserLog, type: .debug)
try adminGroup?.addMemberRecord(newRecord)
if isAdmin, let newRecord = newRecord {
if makeAdmin(newRecord)==false {
os_log("failed to make user an admin", log: createUserLog, type: .error)

} catch {
let errorText = error.localizedDescription
os_log("Unable to add user to administrators group: %{public}@", log: createUserLog, type: .error, errorText)
}
}

Expand Down Expand Up @@ -669,8 +672,8 @@ class XCredsCreateUser: XCredsBaseMechanism {
}

}
fileprivate func updateOIDCInfo(_ user: String, iss:String, sub:String) {
if XCredsCreateUser.updateOIDCInfo(user:user, iss: iss, sub:sub) {
fileprivate func updateOIDCInfo(_ user: String, iss:String, sub:String,groups:[String]?) {
if XCredsCreateUser.updateOIDCInfo(user:user, iss: iss, sub:sub, groups:groups) {
os_log("updateOIDCInfo updated", log: createUserLog, type: .default)
} else {
os_log("Could not add updateOIDCInfo", log: createUserLog, type: .error)
Expand Down
12 changes: 6 additions & 6 deletions xCreds.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1249,7 +1249,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 5273;
CURRENT_PROJECT_VERSION = 5275;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = UXP6YEHSPW;
FRAMEWORK_SEARCH_PATHS = (
Expand Down Expand Up @@ -1287,7 +1287,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 5273;
CURRENT_PROJECT_VERSION = 5275;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = UXP6YEHSPW;
FRAMEWORK_SEARCH_PATHS = (
Expand Down Expand Up @@ -1407,7 +1407,7 @@
CODE_SIGN_ENTITLEMENTS = "XCreds Login Overlay/XCreds_Login_Overlay.entitlements";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 5273;
CURRENT_PROJECT_VERSION = 5275;
DEVELOPMENT_TEAM = UXP6YEHSPW;
ENABLE_HARDENED_RUNTIME = YES;
FRAMEWORK_SEARCH_PATHS = (
Expand Down Expand Up @@ -1444,7 +1444,7 @@
CODE_SIGN_ENTITLEMENTS = "XCreds Login Overlay/XCreds_Login_Overlay.entitlements";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 5273;
CURRENT_PROJECT_VERSION = 5275;
DEVELOPMENT_TEAM = UXP6YEHSPW;
ENABLE_HARDENED_RUNTIME = YES;
FRAMEWORK_SEARCH_PATHS = (
Expand Down Expand Up @@ -1594,7 +1594,7 @@
CODE_SIGN_ENTITLEMENTS = XCreds/xCreds.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 5273;
CURRENT_PROJECT_VERSION = 5275;
DEVELOPMENT_TEAM = UXP6YEHSPW;
ENABLE_HARDENED_RUNTIME = YES;
FRAMEWORK_SEARCH_PATHS = (
Expand Down Expand Up @@ -1635,7 +1635,7 @@
CODE_SIGN_ENTITLEMENTS = XCreds/xCreds.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 5273;
CURRENT_PROJECT_VERSION = 5275;
DEVELOPMENT_TEAM = UXP6YEHSPW;
ENABLE_HARDENED_RUNTIME = YES;
FRAMEWORK_SEARCH_PATHS = (
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,8 @@
filePath = "XCredsLoginPlugIn/LoginWindow/LoginWebViewWindowController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "305"
endingLineNumber = "305"
startingLineNumber = "316"
endingLineNumber = "316"
landmarkName = "tokensUpdated(tokens:)"
landmarkType = "7">
</BreakpointContent>
Expand All @@ -172,8 +172,8 @@
filePath = "NomadLogin/DSQueryable.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "236"
endingLineNumber = "236"
startingLineNumber = "259"
endingLineNumber = "259"
landmarkName = "getAllStandardUsers()"
landmarkType = "7">
</BreakpointContent>
Expand All @@ -188,8 +188,8 @@
filePath = "NomadLogin/DSQueryable.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "250"
endingLineNumber = "250"
startingLineNumber = "273"
endingLineNumber = "273"
landmarkName = "getAllStandardUsers()"
landmarkType = "7">
</BreakpointContent>
Expand All @@ -204,8 +204,8 @@
filePath = "NomadLogin/DSQueryable.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "255"
endingLineNumber = "255"
startingLineNumber = "278"
endingLineNumber = "278"
landmarkName = "getAllStandardUsers()"
landmarkType = "7">
</BreakpointContent>
Expand Down

0 comments on commit 8376942

Please sign in to comment.