Skip to content

Commit b17eb23

Browse files
authored
Merge pull request #1062 from oracle-devrel/oig-loa-account-disable-schedtask
Add a LOA Account Disable scheduled task for OIG
2 parents 2e2bfc7 + 2ea08e3 commit b17eb23

File tree

4 files changed

+290
-0
lines changed

4 files changed

+290
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
Copyright (c) 2024 Oracle and/or its affiliates.
2+
3+
The Universal Permissive License (UPL), Version 1.0
4+
5+
Subject to the condition set forth below, permission is hereby granted to any
6+
person obtaining a copy of this software, associated documentation and/or data
7+
(collectively the "Software"), free of charge and under any and all copyright
8+
rights in the Software, and any and all patent rights owned or freely
9+
licensable by each licensor hereunder covering either (i) the unmodified
10+
Software as contributed to or provided by such licensor, or (ii) the Larger
11+
Works (as defined below), to deal in both
12+
13+
(a) the Software, and
14+
(b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
15+
one is included with the Software (each a "Larger Work" to which the Software
16+
is contributed by such licensors),
17+
18+
without restriction, including without limitation the rights to copy, create
19+
derivative works of, display, perform, and distribute the Software and make,
20+
use, sell, offer for sale, import, export, have made, and have sold the
21+
Software and the Larger Work(s), and to sublicense the foregoing rights on
22+
either these or other terms.
23+
24+
This license is subject to the following condition:
25+
The above copyright notice and either this complete permission notice or at
26+
a minimum a reference to the UPL must be included in all copies or
27+
substantial portions of the Software.
28+
29+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
32+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
34+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
35+
SOFTWARE.
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Leave Of Absence Account Disable Scheduled Task
2+
3+
This asset contains the code and deployment items for a scheduled task designed to disable all active accounts of Oracle Identity Governance users until a certain date value is reached, and the accounts are re-enabled. The data value is stored either in a Date-type UDF (User-defined field) or pre-existing user attribute. Out of the box date fields can also be used since the field name storing the data value can be specified as a scheduler parameter.
4+
5+
Can be used as a basis to demonstrate an alternative "leave of absence" implementation, where the users in question can still log into Oracle Identity Governance, to, for example, participate in approval processes or delegate their rights to a proxy, however they aren't able to access any of the downstream systems for which they have accounts provisioned by Oracle Identity Governance while the LOA is in effect.
6+
7+
Developed on and compatible with OIG 11g R2 PS3 and above.
8+
9+
Review Date: 28.10.2024
10+
11+
# When to use this asset?
12+
13+
When there's a need to provide or demonstrate the functionality described above or something similar, which can be adapted from the provided code.
14+
15+
# How to use this asset?
16+
17+
## Building and deployment
18+
19+
Here's a short build and deployment checklist:
20+
21+
1. Generate a jar file containing the sample code.
22+
2. Upload the jar file to an OIG environment using OIG's command line "Jar Upload" utility.
23+
3. Use the Enterprise Manager web interface to upload the scheduled task metadata/definition into the MDS repository.
24+
4. Create a scheduled task in OIG based on the uploaded definition.
25+
26+
Please see the useful link below for detailed build and deployment steps.
27+
28+
## Executing the scheduled task
29+
30+
- Ensure you have specified a relevant value for the `LOA end date user attribute` scheduler parameter field in the scheduled task definition. Note that a either a UDF (User-defined field) or a pre-existing user attribute can be used. This value needs to contain the attribute's display label, not the backend name (e.g., `User Login`, not `USR_LOGIN`).
31+
32+
- [Consult this section](https://docs.oracle.com/en/middleware/idm/identity-governance/12.2.1.4/omusg/managing-jobs-1.html#GUID-71BB3623-AEE2-4F64-BBD4-D921DCA39D7C) on how to manually start or schedule a job.
33+
34+
# Useful Links
35+
36+
[Oracle Identity Governance developer's guide - Developing scheduled tasks](https://docs.oracle.com/en/middleware/idm/identity-governance/12.2.1.4/omdev/developing-scheduled-tasks.html#GUID-F62EF833-1E70-41FC-9DCC-C1EAB407D151)
37+
38+
# License
39+
40+
Copyright (c) 2024 Oracle and/or its affiliates.
41+
42+
Licensed under the Universal Permissive License (UPL), Version 1.0.
43+
44+
See [LICENSE](https://github.com/oracle-devrel/technology-engineering/blob/main/LICENSE) for more details.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version='1.0' encoding='UTF-8'?>
2+
<scheduledTasks xmlns="http://xmlns.oracle.com/oim/scheduler">
3+
<task>
4+
<name>LOA Account Disable</name>
5+
<class>com.oracle.sample.LOAAccountDisable</class>
6+
<description>LOA Account Disable</description>
7+
<retry>1</retry>
8+
<parameters>
9+
<string-param required="true" encrypted="false" helpText="The name of the user attribute storing the LOA end date.">LOA end date user attribute</string-param>
10+
</parameters>
11+
</task>
12+
</scheduledTasks>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved. DO NOT
3+
* ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* The Universal Permissive License (UPL), Version 1.0
6+
*
7+
* Subject to the condition set forth below, permission is hereby granted to any
8+
* person obtaining a copy of this software, associated documentation and/or
9+
* data (collectively the "Software"), free of charge and under any and all
10+
* copyright rights in the Software, and any and all patent rights owned or
11+
* freely licensable by each licensor hereunder covering either (i) the
12+
* unmodified Software as contributed to or provided by such licensor, or (ii)
13+
* the Larger Works (as defined below), to deal in both
14+
*
15+
* (a) the Software, and
16+
*
17+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
18+
* one is included with the Software each a "Larger Work" to which the Software
19+
* is contributed by such licensors),
20+
*
21+
* without restriction, including without limitation the rights to copy, create
22+
* derivative works of, display, perform, and distribute the Software and make,
23+
* use, sell, offer for sale, import, export, have made, and have sold the
24+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
25+
* either these or other terms.
26+
*
27+
* This license is subject to the following condition:
28+
*
29+
* The above copyright notice and either this complete permission notice or at a
30+
* minimum a reference to the UPL must be included in all copies or substantial
31+
* portions of the Software.
32+
*
33+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39+
* SOFTWARE.
40+
*******************************************************************************/
41+
42+
package com.oracle.sample;
43+
44+
import java.util.Calendar;
45+
46+
import java.util.Date;
47+
import java.util.HashMap;
48+
import java.util.HashSet;
49+
import java.util.List;
50+
import java.util.Set;
51+
import java.util.concurrent.TimeUnit;
52+
import java.util.logging.Level;
53+
import java.util.logging.Logger;
54+
55+
import oracle.iam.identity.usermgmt.api.UserManager;
56+
import oracle.iam.identity.usermgmt.api.UserManagerConstants;
57+
import oracle.iam.identity.usermgmt.vo.User;
58+
import oracle.iam.platform.Platform;
59+
import oracle.iam.platform.entitymgr.vo.SearchCriteria;
60+
import oracle.iam.provisioning.api.ProvisioningConstants;
61+
import oracle.iam.provisioning.api.ProvisioningService;
62+
import oracle.iam.provisioning.vo.Account;
63+
import oracle.iam.scheduler.exception.SchedulerException;
64+
import oracle.iam.scheduler.vo.TaskSupport;
65+
66+
/**
67+
* Sample scheduled task implementation that disables all the access of a user
68+
* which goes on a leave of absence. The LOA status is determined based on a
69+
* custom attribute (UDF), specified as a parameter in the scheduled task
70+
* definition.
71+
*
72+
* The scheduled task will also handle the re-enabling of user accounts once the
73+
* LOA end date is hit, and also the clearing of the UDF value which signifies
74+
* the LOA state.
75+
*
76+
* @author mgere-oracle
77+
*/
78+
public class LOAAccountDisable extends TaskSupport {
79+
80+
private static final Logger logger = Logger.getLogger(LOAAccountDisable.class.getName());
81+
82+
@Override
83+
public void execute(HashMap arg0) throws Exception {
84+
logger.log(Level.INFO, "The scheduled task run has started.");
85+
86+
if (arg0 == null) {
87+
// arg0 will never be null if a valid scheduled task definition file is used
88+
throw new SchedulerException("Scheduled task definition is incorrect. Aborting run.");
89+
}
90+
91+
UserManager userManager = Platform.getService(UserManager.class);
92+
ProvisioningService provService = Platform.getService(ProvisioningService.class);
93+
94+
final String LOA_DATE_FIELD_NAME = (String) arg0.get("LOA end date user attribute");
95+
logger.log(Level.FINE, "LOA_DATE_FIELD_NAME: {0}", LOA_DATE_FIELD_NAME);
96+
97+
// construct a criteria for all active users in the system;
98+
// note that user access is disabled in this case, not the users themselves
99+
SearchCriteria userSearchCriteriaActive = new SearchCriteria(UserManagerConstants.AttributeName.STATUS.getId(),
100+
UserManagerConstants.AttributeValues.USER_STATUS_ACTIVE.getId(), SearchCriteria.Operator.EQUAL);
101+
Set<String> retAttrs = new HashSet<>();
102+
103+
List<User> activeUserList = userManager.search(userSearchCriteriaActive, retAttrs, null);
104+
Date currentDate = Calendar.getInstance().getTime();
105+
logger.log(Level.FINE, "Current date: {0}", currentDate);
106+
107+
for (User currentUser : activeUserList) {
108+
try {
109+
Date loaAccountDisableDate = (Date) currentUser.getAttribute(LOA_DATE_FIELD_NAME);
110+
111+
if (loaAccountDisableDate != null) {
112+
logger.log(Level.INFO, "Processing user: {0}", currentUser.getLogin());
113+
logger.log(Level.FINE, "LOA account disable date: {0}", loaAccountDisableDate);
114+
115+
String userStatus = currentUser.getStatus();
116+
logger.log(Level.FINE, "User status: {0}", userStatus);
117+
118+
// calculate the difference in days between the LOA account disable date,
119+
// typically set in the future, and the current date
120+
Long dayDiff = TimeUnit.DAYS.convert(loaAccountDisableDate.getTime() - currentDate.getTime(),
121+
TimeUnit.MILLISECONDS);
122+
logger.log(Level.FINE, "Time diff: {0}", dayDiff);
123+
124+
if (dayDiff <= 0
125+
&& userStatus.equals(UserManagerConstants.AttributeValues.USER_STATUS_ACTIVE.getId())) {
126+
logger.log(Level.INFO, "Parental leave date has been hit. Enabling user accounts...");
127+
128+
SearchCriteria disableAccountSearch = new SearchCriteria(
129+
ProvisioningConstants.AccountSearchAttribute.ACCOUNT_STATUS.getId(),
130+
ProvisioningConstants.ObjectStatus.DISABLED.getId(), SearchCriteria.Operator.EQUAL);
131+
List<Account> disabledAccounts = provService.getAccountsProvisionedToUser(currentUser.getId(),
132+
disableAccountSearch, null);
133+
134+
for (Account currentDisabledAccount : disabledAccounts) {
135+
try {
136+
logger.log(Level.INFO, "Enabling user account: {0}",
137+
currentDisabledAccount.getAccountDescriptiveField());
138+
provService.enable(Long.parseLong(currentDisabledAccount.getAccountID()));
139+
logger.log(Level.INFO, "Account enabled.");
140+
} catch (Exception e) {
141+
logger.log(Level.WARNING, "Enabling of account has failed: ", e);
142+
}
143+
}
144+
145+
logger.log(Level.INFO, "Clearing LOA end date value...");
146+
User updatedUser = new User(currentUser.getId());
147+
updatedUser.setAttribute(LOA_DATE_FIELD_NAME, "");
148+
userManager.modify(updatedUser);
149+
logger.log(Level.INFO, "LOA end date cleared.");
150+
151+
} else if (dayDiff > 0
152+
&& userStatus.equals(UserManagerConstants.AttributeValues.USER_STATUS_ACTIVE.getId())) {
153+
logger.log(Level.INFO, "A future LOA end date is set. Disabling user accounts...");
154+
155+
// only list provisioned or enabled accounts, as those will be eligible for disabling
156+
SearchCriteria provisionedAccountSearch = new SearchCriteria(
157+
ProvisioningConstants.AccountSearchAttribute.ACCOUNT_STATUS.getId(),
158+
ProvisioningConstants.ObjectStatus.PROVISIONED.getId(), SearchCriteria.Operator.EQUAL);
159+
SearchCriteria enabledAccountSearch = new SearchCriteria(
160+
ProvisioningConstants.AccountSearchAttribute.ACCOUNT_STATUS.getId(),
161+
ProvisioningConstants.ObjectStatus.ENABLED.getId(), SearchCriteria.Operator.EQUAL);
162+
SearchCriteria activeAccountsSearch = new SearchCriteria(provisionedAccountSearch,
163+
enabledAccountSearch, SearchCriteria.Operator.OR);
164+
165+
List<Account> activeAccounts = provService.getAccountsProvisionedToUser(currentUser.getId(),
166+
activeAccountsSearch, null);
167+
168+
for (Account currentAccount : activeAccounts) {
169+
try {
170+
logger.log(Level.INFO, "Disabling user account: {0}",
171+
currentAccount.getAccountDescriptiveField());
172+
provService.disable(Long.parseLong(currentAccount.getAccountID()));
173+
logger.log(Level.INFO, "Account disabled.");
174+
} catch (Exception e) {
175+
logger.log(Level.WARNING, "Disabling of account has failed: ", e);
176+
}
177+
}
178+
}
179+
} else {
180+
logger.log(Level.FINE, "LOA end date not set. Skipping.");
181+
}
182+
} catch (Exception e) {
183+
logger.log(Level.WARNING, "User processing failed: ", e);
184+
}
185+
}
186+
187+
logger.log(Level.INFO, "The scheduled task run has finished.");
188+
}
189+
190+
@SuppressWarnings("rawtypes")
191+
@Override
192+
public HashMap getAttributes() {
193+
return new HashMap<>();
194+
}
195+
196+
@Override
197+
public void setAttributes() {
198+
}
199+
}

0 commit comments

Comments
 (0)