[KEYCLOAK-3337] - Support more specific date/time periods with the Time policy provider

This commit is contained in:
Pedro Igor 2016-08-30 16:32:00 -03:00
parent 5a4bb5f3f0
commit 73bcfba5f3
5 changed files with 137 additions and 11 deletions

View file

@ -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

View file

@ -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();

View file

@ -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

View file

@ -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) {

View file

@ -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()"/>&nbsp;&nbsp;to&nbsp;&nbsp;<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()"/>&nbsp;&nbsp;to&nbsp;&nbsp;<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()"/>&nbsp;&nbsp;to&nbsp;&nbsp;<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()"/>&nbsp;&nbsp;to&nbsp;&nbsp;<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()"/>&nbsp;&nbsp;to&nbsp;&nbsp;<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>