[KEYCLOAK-3337] - Support more specific date/time periods with the Time policy provider
This commit is contained in:
parent
5a4bb5f3f0
commit
73bcfba5f3
5 changed files with 137 additions and 11 deletions
|
@ -37,12 +37,10 @@ public class TimePolicyAdminResource implements PolicyProviderAdminService {
|
||||||
String nbf = policy.getConfig().get("nbf");
|
String nbf = policy.getConfig().get("nbf");
|
||||||
String noa = policy.getConfig().get("noa");
|
String noa = policy.getConfig().get("noa");
|
||||||
|
|
||||||
if (nbf == null && noa == null) {
|
if (nbf != null && noa != null) {
|
||||||
throw new RuntimeException("You must provide NotBefore, NotOnOrAfter or both.");
|
validateFormat(nbf);
|
||||||
|
validateFormat(noa);
|
||||||
}
|
}
|
||||||
|
|
||||||
validateFormat(nbf);
|
|
||||||
validateFormat(noa);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -22,8 +22,11 @@ import org.keycloak.authorization.policy.evaluation.Evaluation;
|
||||||
import org.keycloak.authorization.policy.provider.PolicyProvider;
|
import org.keycloak.authorization.policy.provider.PolicyProvider;
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
import static com.sun.corba.se.spi.activation.IIOP_CLEAR_TEXT.value;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||||
*/
|
*/
|
||||||
|
@ -45,9 +48,7 @@ public class TimePolicyProvider implements PolicyProvider {
|
||||||
public void evaluate(Evaluation evaluation) {
|
public void evaluate(Evaluation evaluation) {
|
||||||
try {
|
try {
|
||||||
String notBefore = this.policy.getConfig().get("nbf");
|
String notBefore = this.policy.getConfig().get("nbf");
|
||||||
|
|
||||||
if (notBefore != null) {
|
if (notBefore != null) {
|
||||||
|
|
||||||
if (this.currentDate.before(this.dateFormat.parse(format(notBefore)))) {
|
if (this.currentDate.before(this.dateFormat.parse(format(notBefore)))) {
|
||||||
evaluation.deny();
|
evaluation.deny();
|
||||||
return;
|
return;
|
||||||
|
@ -55,7 +56,6 @@ public class TimePolicyProvider implements PolicyProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
String notOnOrAfter = this.policy.getConfig().get("noa");
|
String notOnOrAfter = this.policy.getConfig().get("noa");
|
||||||
|
|
||||||
if (notOnOrAfter != null) {
|
if (notOnOrAfter != null) {
|
||||||
if (this.currentDate.after(this.dateFormat.parse(format(notOnOrAfter)))) {
|
if (this.currentDate.after(this.dateFormat.parse(format(notOnOrAfter)))) {
|
||||||
evaluation.deny();
|
evaluation.deny();
|
||||||
|
@ -63,12 +63,48 @@ public class TimePolicyProvider implements PolicyProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isInvalid(Calendar.DAY_OF_MONTH, "dayMonth")
|
||||||
|
|| isInvalid(Calendar.MONTH, "month")
|
||||||
|
|| isInvalid(Calendar.YEAR, "year")
|
||||||
|
|| isInvalid(Calendar.HOUR_OF_DAY, "hour")
|
||||||
|
|| isInvalid(Calendar.MINUTE, "minute")) {
|
||||||
|
evaluation.deny();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
evaluation.grant();
|
evaluation.grant();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException("Could not evaluate time-based policy [" + this.policy.getName() + "].", e);
|
throw new RuntimeException("Could not evaluate time-based policy [" + this.policy.getName() + "].", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isInvalid(int timeConstant, String configName) {
|
||||||
|
Calendar calendar = Calendar.getInstance();
|
||||||
|
|
||||||
|
calendar.setTime(this.currentDate);
|
||||||
|
|
||||||
|
int dateField = calendar.get(timeConstant);
|
||||||
|
|
||||||
|
if (Calendar.MONTH == timeConstant) {
|
||||||
|
dateField++;
|
||||||
|
}
|
||||||
|
|
||||||
|
String start = this.policy.getConfig().get(configName);
|
||||||
|
if (start != null) {
|
||||||
|
String end = this.policy.getConfig().get(configName + "End");
|
||||||
|
if (end != null) {
|
||||||
|
if (dateField < Integer.parseInt(start) || dateField > Integer.parseInt(end)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (dateField != Integer.parseInt(start)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static String format(String notBefore) {
|
static String format(String notBefore) {
|
||||||
String trimmed = notBefore.trim();
|
String trimmed = notBefore.trim();
|
||||||
|
|
||||||
|
|
|
@ -1051,6 +1051,16 @@ authz-add-time-policy=Add Time Policy
|
||||||
authz-policy-time-not-before.tooltip=Defines the time before which the policy MUST NOT be granted. Only granted if current date/time is after or equal to this value.
|
authz-policy-time-not-before.tooltip=Defines the time before which the policy MUST NOT be granted. Only granted if current date/time is after or equal to this value.
|
||||||
authz-policy-time-not-on-after=Not On or After
|
authz-policy-time-not-on-after=Not On or After
|
||||||
authz-policy-time-not-on-after.tooltip=Defines the time after which the policy MUST NOT be granted. Only granted if current date/time is before or equal to this value.
|
authz-policy-time-not-on-after.tooltip=Defines the time after which the policy MUST NOT be granted. Only granted if current date/time is before or equal to this value.
|
||||||
|
authz-policy-time-day-month=Day of Month
|
||||||
|
authz-policy-time-day-month.tooltip=Defines the day of month before/equal which policy MUST be granted. You can also provide a range period by filling the second field with the day of month before/equal which the policy MUST be granted. In this case, the policy would be granted if current day of month is between/equal the two values you provided.
|
||||||
|
authz-policy-time-month=Month
|
||||||
|
authz-policy-time-month.tooltip=Defines the month before/equal which policy MUST be granted. You can also provide a range period by filling the second field with the month before/equal which the policy MUST be granted. In this case, the policy would be granted if current month is between/equal the two values you provided.
|
||||||
|
authz-policy-time-year=Year
|
||||||
|
authz-policy-time-year.tooltip=Defines the year before/equal which policy MUST be granted. You can also provide a range period by filling the second field with the year before/equal which the policy MUST be granted. In this case, the policy would be granted if current year is between/equal the two values you provided.
|
||||||
|
authz-policy-time-hour=Hour
|
||||||
|
authz-policy-time-hour.tooltip=Defines the hour before/equal which policy MUST be granted. You can also provide a range period by filling the second field with the hour before/equal which the policy MUST be granted. In this case, the policy would be granted if current hour is between/equal the two values you provided.
|
||||||
|
authz-policy-time-minute=Minute
|
||||||
|
authz-policy-time-minute.tooltip=Defines the minute before/equal which policy MUST be granted. You can also provide a range period by filling the second field with the minute before/equal which the policy MUST be granted. In this case, the policy would be granted if current minute is between/equal the two values you provided.
|
||||||
|
|
||||||
# Authz Drools Policy Detail
|
# Authz Drools Policy Detail
|
||||||
authz-add-drools-policy=Add Drools Policy
|
authz-add-drools-policy=Add Drools Policy
|
||||||
|
|
|
@ -1090,7 +1090,36 @@ module.controller('ResourceServerPolicyTimeDetailCtrl', function($scope, $route,
|
||||||
},
|
},
|
||||||
|
|
||||||
onInitUpdate : function(policy) {
|
onInitUpdate : function(policy) {
|
||||||
|
if (policy.config.dayMonth) {
|
||||||
|
policy.config.dayMonth = parseInt(policy.config.dayMonth);
|
||||||
|
}
|
||||||
|
if (policy.config.dayMonthEnd) {
|
||||||
|
policy.config.dayMonthEnd = parseInt(policy.config.dayMonthEnd);
|
||||||
|
}
|
||||||
|
if (policy.config.month) {
|
||||||
|
policy.config.month = parseInt(policy.config.month);
|
||||||
|
}
|
||||||
|
if (policy.config.monthEnd) {
|
||||||
|
policy.config.monthEnd = parseInt(policy.config.monthEnd);
|
||||||
|
}
|
||||||
|
if (policy.config.year) {
|
||||||
|
policy.config.year = parseInt(policy.config.year);
|
||||||
|
}
|
||||||
|
if (policy.config.yearEnd) {
|
||||||
|
policy.config.yearEnd = parseInt(policy.config.yearEnd);
|
||||||
|
}
|
||||||
|
if (policy.config.hour) {
|
||||||
|
policy.config.hour = parseInt(policy.config.hour);
|
||||||
|
}
|
||||||
|
if (policy.config.hourEnd) {
|
||||||
|
policy.config.hourEnd = parseInt(policy.config.hourEnd);
|
||||||
|
}
|
||||||
|
if (policy.config.minute) {
|
||||||
|
policy.config.minute = parseInt(policy.config.minute);
|
||||||
|
}
|
||||||
|
if (policy.config.minuteEnd) {
|
||||||
|
policy.config.minuteEnd = parseInt(policy.config.minuteEnd);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onUpdate : function() {
|
onUpdate : function() {
|
||||||
|
@ -1106,6 +1135,19 @@ module.controller('ResourceServerPolicyTimeDetailCtrl', function($scope, $route,
|
||||||
|
|
||||||
}
|
}
|
||||||
}, realm, client, $scope);
|
}, realm, client, $scope);
|
||||||
|
|
||||||
|
$scope.isRequired = function () {
|
||||||
|
var policy = $scope.policy;
|
||||||
|
if (policy.config.noa || policy.config.nbf
|
||||||
|
|| policy.config.dayMonth
|
||||||
|
|| policy.config.month
|
||||||
|
|| policy.config.year
|
||||||
|
|| policy.config.hour
|
||||||
|
|| policy.config.minute) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
module.controller('ResourceServerPolicyAggregateDetailCtrl', function($scope, $route, $location, realm, PolicyController, ResourceServerPolicy, client) {
|
module.controller('ResourceServerPolicyAggregateDetailCtrl', function($scope, $route, $location, realm, PolicyController, ResourceServerPolicy, client) {
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
<label class="col-md-2 control-label" for="policy.config.nbf">{{:: 'not-before' | translate}}</label>
|
<label class="col-md-2 control-label" for="policy.config.nbf">{{:: 'not-before' | translate}}</label>
|
||||||
|
|
||||||
<div class="col-md-6 time-selector">
|
<div class="col-md-6 time-selector">
|
||||||
<input class="form-control" style="width: 150px" type="text" id="policy.config.nbf" name="notBefore" data-ng-model="policy.config.nbf" placeholder="yyyy-MM-dd hh:mm:ss">
|
<input class="form-control" style="width: 150px" type="text" id="policy.config.nbf" name="notBefore" data-ng-model="policy.config.nbf" placeholder="yyyy-MM-dd hh:mm:ss" data-ng-required="isRequired()">
|
||||||
</div>
|
</div>
|
||||||
<kc-tooltip>{{:: 'authz-policy-time-not-before.tooltip' | translate}}</kc-tooltip>
|
<kc-tooltip>{{:: 'authz-policy-time-not-before.tooltip' | translate}}</kc-tooltip>
|
||||||
</div>
|
</div>
|
||||||
|
@ -45,10 +45,50 @@
|
||||||
<label class="col-md-2 control-label" for="policy.config.noa">{{:: 'authz-policy-time-not-on-after' | translate}}</label>
|
<label class="col-md-2 control-label" for="policy.config.noa">{{:: 'authz-policy-time-not-on-after' | translate}}</label>
|
||||||
|
|
||||||
<div class="col-md-6 time-selector">
|
<div class="col-md-6 time-selector">
|
||||||
<input class="form-control" style="width: 150px" type="text" id="policy.config.noa" name="policy.config.noa" data-ng-model="policy.config.noa" placeholder="yyyy-MM-dd hh:mm:ss">
|
<input class="form-control" style="width: 150px" type="text" id="policy.config.noa" name="policy.config.noa" data-ng-model="policy.config.noa" placeholder="yyyy-MM-dd hh:mm:ss" data-ng-required="isRequired()">
|
||||||
</div>
|
</div>
|
||||||
<kc-tooltip>{{:: 'authz-policy-time-not-on-after.tooltip' | translate}}</kc-tooltip>
|
<kc-tooltip>{{:: 'authz-policy-time-not-on-after.tooltip' | translate}}</kc-tooltip>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-2 control-label" for="policy.config.noa">{{:: 'authz-policy-time-day-month' | translate}}</label>
|
||||||
|
|
||||||
|
<div class="col-md-6 time-selector">
|
||||||
|
<input class="form-control" type="number" min="1" max="31" data-ng-model="policy.config.dayMonth" id="dayMonth" name="dayMonth" data-ng-required="isRequired()"/> to <input class="form-control" type="number" min="{{policy.config.dayMonth}}" max="31" data-ng-model="policy.config.dayMonthEnd" id="dayMonthEnd" name="dayMonthEnd"/>
|
||||||
|
</div>
|
||||||
|
<kc-tooltip>{{:: 'authz-policy-time-day-month.tooltip' | translate}}</kc-tooltip>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-2 control-label" for="policy.config.noa">{{:: 'authz-policy-time-month' | translate}}</label>
|
||||||
|
|
||||||
|
<div class="col-md-6 time-selector">
|
||||||
|
<input class="form-control" type="number" min="1" max="12" data-ng-model="policy.config.month" id="month" name="month" data-ng-required="isRequired()"/> to <input class="form-control" type="number" min="{{policy.config.month}}" max="12" data-ng-model="policy.config.monthEnd" id="monthEnd" name="monthEnd"/>
|
||||||
|
</div>
|
||||||
|
<kc-tooltip>{{:: 'authz-policy-time-month.tooltip' | translate}}</kc-tooltip>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-2 control-label" for="policy.config.noa">{{:: 'authz-policy-time-year' | translate}}</label>
|
||||||
|
|
||||||
|
<div class="col-md-6 time-selector">
|
||||||
|
<input class="form-control" type="number" min="2016" max="2050" data-ng-model="policy.config.year" id="year" name="year" data-ng-required="isRequired()"/> to <input class="form-control" type="number" min="{{policy.config.year}}" max="2050" data-ng-model="policy.config.yearEnd" id="yearEnd" name="yearEnd"/>
|
||||||
|
</div>
|
||||||
|
<kc-tooltip>{{:: 'authz-policy-time-year.tooltip' | translate}}</kc-tooltip>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-2 control-label" for="policy.config.noa">{{:: 'authz-policy-time-hour' | translate}}</label>
|
||||||
|
|
||||||
|
<div class="col-md-6 time-selector">
|
||||||
|
<input class="form-control" type="number" min="0" max="23" data-ng-model="policy.config.hour" id="hour" name="hour" data-ng-required="isRequired()"/> to <input class="form-control" type="number" min="{{policy.config.hour}}" max="23" data-ng-model="policy.config.hourEnd" id="hourEnd" name="hourEnd"/>
|
||||||
|
</div>
|
||||||
|
<kc-tooltip>{{:: 'authz-policy-time-hour.tooltip' | translate}}</kc-tooltip>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-2 control-label" for="policy.config.noa">{{:: 'authz-policy-time-minute' | translate}}</label>
|
||||||
|
|
||||||
|
<div class="col-md-6 time-selector">
|
||||||
|
<input class="form-control" type="number" min="0" max="59" data-ng-model="policy.config.minute" id="minute" name="minute" data-ng-required="isRequired()"/> to <input class="form-control" type="number" min="{{policy.config.minute}}" max="59" data-ng-model="policy.config.minuteEnd" id="minuteEnd" name="minuteEnd"/>
|
||||||
|
</div>
|
||||||
|
<kc-tooltip>{{:: 'authz-policy-time-minute.tooltip' | translate}}</kc-tooltip>
|
||||||
|
</div>
|
||||||
<div class="form-group clearfix">
|
<div class="form-group clearfix">
|
||||||
<label class="col-md-2 control-label" for="policy.logic">{{:: 'authz-policy-logic' | translate}}</label>
|
<label class="col-md-2 control-label" for="policy.logic">{{:: 'authz-policy-logic' | translate}}</label>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue