Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/dev-sjones-euca-12829'
Browse files Browse the repository at this point in the history
  • Loading branch information
sjones4 committed Oct 18, 2016
2 parents 8b3be34 + 1866049 commit 94c0a22
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 78 deletions.
Expand Up @@ -137,6 +137,9 @@ public class AuthenticationProperties {
@ConfigurableField( description = "Maximum size for an IAM policy (bytes)", initial = DEFAULT_MAX_POLICY_SIZE_TEXT )
public static volatile int MAX_POLICY_SIZE = Integer.parseInt( DEFAULT_MAX_POLICY_SIZE_TEXT );

@ConfigurableField( description = "Use strict validation for IAM policy syntax", initial = "true" )
public static volatile boolean STRICT_POLICY_VALIDATION = true;

private static AtomicLong DEFAULT_PASSWORD_EXPIRY_MILLIS = new AtomicLong( TimeUnit.DAYS.toMillis( 60 ) );

private static AtomicLong AUTHORIZATION_EXPIRY_MILLIS = new AtomicLong( TimeUnit.SECONDS.toMillis( 5 ) );
Expand Down Expand Up @@ -242,6 +245,11 @@ public int getSigningCertificateLimitSpi( ) {
public int getPolicySizeLimitSpi( ) {
return MAX_POLICY_SIZE;
}

@Override
public boolean getUseValidatingPolicyParserSpi( ) {
return STRICT_POLICY_VALIDATION;
}
}

public static final class AuthenticationIntervalPropertyChangeListener implements PropertyChangeListener {
Expand Down
Expand Up @@ -36,6 +36,8 @@ public interface AuthenticationLimitProvider {

int getPolicySizeLimitSpi( );

boolean getUseValidatingPolicyParserSpi( );

class Values {
public static long getDefaultPasswordExpiry( ) {
return getLongValue( AuthenticationLongProperties.DEFAULT_PASSWORD_EXPIRY );
Expand All @@ -57,6 +59,10 @@ public static int getPolicySizeLimit( ) {

public static int getOpenIdConnectProviderThumprintLimit( ) { return 5; }

public static boolean getUseValidatingPolicyParser( ) {
return getBooleanValue( AuthenticationBooleanProperties.USE_VALIDATING );
}

static int getIntValue( final NonNullFunction<AuthenticationLimitProvider, Integer> valueFunction ) {
return getValue( valueFunction );
}
Expand All @@ -65,6 +71,10 @@ static long getLongValue( final NonNullFunction<AuthenticationLimitProvider, Lon
return getValue( valueFunction );
}

static boolean getBooleanValue( final NonNullFunction<AuthenticationLimitProvider, Boolean> valueFunction ) {
return getValue( valueFunction );
}

static <VT> VT getValue(
final NonNullFunction<AuthenticationLimitProvider, VT> valueFunction
) {
Expand Down Expand Up @@ -105,4 +115,18 @@ public Long apply( final AuthenticationLimitProvider authenticationLimitProvider
}
},
}

enum AuthenticationBooleanProperties implements NonNullFunction<AuthenticationLimitProvider, Boolean> {
USE_VALIDATING {
@Nonnull
@Override
public Boolean apply( final AuthenticationLimitProvider authenticationLimitProvider ) {
return authenticationLimitProvider.getUseValidatingPolicyParserSpi();
}
}
}


}


Expand Up @@ -122,7 +122,7 @@
* The implementation of policy engine, which evaluates a request against specified policies.
*/
public class PolicyEngineImpl implements PolicyEngine {

private static final Logger LOG = Logger.getLogger( PolicyEngineImpl.class );

private static final Cache<String,ImmutableList<Authorization>> authorizationCache = CacheBuilder
Expand All @@ -145,11 +145,11 @@ private enum Decision {
DENY, // explicit deny
ALLOW, // explicit allow
}

private interface Matcher {
boolean match( String pattern, String instance );
}

private static final Matcher PATTERN_MATCHER = new Matcher( ) {
@Override
public boolean match( String pattern, String instance ) {
Expand All @@ -160,7 +160,7 @@ public boolean match( String pattern, String instance ) {
return Pattern.matches( pattern, instance );
}
};

private static final Matcher ADDRESS_MATCHER = new Matcher( ) {
@Override
public boolean match( String pattern, String instance ) {
Expand All @@ -170,7 +170,7 @@ public boolean match( String pattern, String instance ) {
return AddressUtil.addressRangeMatch( pattern, instance );
}
};

private static final Matcher SERVER_CERTIFICATE_MATCHER = new Matcher( ) {
@Override
public boolean match( String pattern, String instance ) {
Expand All @@ -179,7 +179,7 @@ public boolean match( String pattern, String instance ) {
// instance is in full ARN form while pattern is /{cert_name};
if(! instance.startsWith("arn:aws:iam::"))
return false;

int idx = instance.indexOf(":server-certificate");
if(idx<0)
return false;
Expand All @@ -191,7 +191,7 @@ public boolean match( String pattern, String instance ) {
return Pattern.matches( pattern, certPathAndName );
}
};

public PolicyEngineImpl(
@Nonnull final Supplier<Boolean> enableSystemQuotas,
@Nonnull final Supplier<String> region
Expand All @@ -213,7 +213,7 @@ public PolicyEngineImpl(
* The authorization evaluation algorithm is a combination of AWS IAM policy evaluation logic and
* AWS inter-account permission checking logic (including EC2 image and snapshot permission, and
* S3 bucket ACL and bucket policy). The algorithm is described in the following:
*
*
* 1. If request user is system admin, access is GRANTED.
* 2. Otherwise, check global (inter-account) authorizations, which are attached to account admin.
* If explicitly denied, access is DENIED.
Expand All @@ -225,7 +225,7 @@ public PolicyEngineImpl(
* 4. Otherwise, check local (intra-account) authorizations.
* If explicitly or default denied, access is DENIED.
* If explicitly allowed, access is GRANTED.
*
*
* (non-Javadoc)
* @see com.eucalyptus.auth.api.PolicyEngine#evaluateAuthorization(java.lang.Class, java.lang.String, java.lang.String)
*/
Expand All @@ -238,11 +238,11 @@ public void evaluateAuthorization( @Nonnull final AuthEvaluationContext context
try {
final AuthEvaluationContextImpl evaluationContext = (AuthEvaluationContextImpl)context;
if ( Decision.ALLOW != evaluateResourceAuthorization(
evaluationContext,
evaluationContext,
authorizationMatch,
!evaluationContext.isSystemUser( ),
resourceAccountNumber,
resourceName,
resourceAccountNumber,
resourceName,
contracts ) ) {
throw new AuthException( AuthException.ACCESS_DENIED );
}
Expand All @@ -252,7 +252,7 @@ public void evaluateAuthorization( @Nonnull final AuthEvaluationContext context
} catch ( Exception e ) {
LOG.debug( e, e );
throw new AuthException( "An error occurred while trying to evaluate policy for resource access", e );
}
}
}

@Override
Expand Down Expand Up @@ -326,7 +326,7 @@ public void evaluateQuota( @Nonnull final AuthEvaluationContext context,
quantity );
}
} catch ( AuthException e ) {
//throw by the policy engine implementation
//throw by the policy engine implementation
throw e;
} catch ( Exception e ) {
throw new AuthException( "An error occurred while trying to evaluate policy for resource allocation.", e );
Expand Down Expand Up @@ -440,11 +440,11 @@ private Decision processAuthorizations( @Nonnull final List<Authorization> auth
return Decision.DENY;
} else {
result = Decision.ALLOW;
}
}
}
return result;
}

private boolean matchActions( Authorization auth, String action ) throws AuthException {
return evaluateElement( matchOne( auth.getActions( ), action, PATTERN_MATCHER ), auth.isNotAction( ) );
}
Expand Down Expand Up @@ -480,11 +480,11 @@ private boolean matchResources( @Nonnull Authorization auth,
return evaluateElement( matchOne( auth.getPolicyVariables( ), auth.getResources( ), resource, PATTERN_MATCHER ), auth.isNotResource( ) );
}
}

private static boolean matchOne( Set<String> patterns, String instance, Matcher matcher ) throws AuthException {
return matchOne( Collections.<String>emptySet( ), patterns, instance, matcher );
}

private static boolean matchOne( Set<String> variables, Set<String> patterns, String instance, Matcher matcher ) throws AuthException {
for ( String pattern : patterns ) {
if ( matcher.match( variableExplode( variables, pattern ) , instance ) ) {
Expand All @@ -496,35 +496,35 @@ private static boolean matchOne( Set<String> variables, Set<String> patterns, St

private static String variableExplode( Set<String> variables, String text ) throws AuthException {
if ( variables.isEmpty( ) ) return text;

String result = text;
for ( final String variable : variables ) {
final String variableValue = PolicyVariables.getPolicyVariable( variable ).evaluate( );
//TODO: variable values cannot currently contain ? or *, if they could we would need
//TODO: to escape the values when they were used in regex matches
result = result.replace( variable, variableValue );
result = result.replace( variable, variableValue );
}

return result;
}

private String resolveAccount( final String accountNumberOrAlias ) {
return accountResolver.apply( accountNumberOrAlias );
}

private boolean evaluateElement( boolean patternMatched, boolean isNot ) {
return ( ( patternMatched && !isNot ) || ( !patternMatched && isNot ) );
}

/**
* Evaluate conditions for an authorization.
*/
private boolean evaluateConditions(
private boolean evaluateConditions(
final Set<String> policyVariables,
final List<? extends Condition> conditions,
final String action,
final CachedKeyEvaluator keyEval,
final ContractKeyEvaluator contractEval
final List<? extends Condition> conditions,
final String action,
final CachedKeyEvaluator keyEval,
final ContractKeyEvaluator contractEval
) throws AuthException {
for ( Condition cond : conditions ) {
ConditionOp op = Conditions.getOpInstance( cond.getType( ) );
Expand All @@ -547,10 +547,10 @@ private boolean evaluateConditions(
}
return true;
}

/**
* Process each of the quota authorizations. If any of them is exceeded, deny access.
*
*
* @param quotas The quota authorizations
* @param action The request action.
* @param resourceType The resource type for allocation
Expand Down Expand Up @@ -603,10 +603,10 @@ private void processQuotas( final List<Pair<PolicyVersion,Authorization>> quotas
}
}
}

/**
* Get the principal ID for an authorization based on scope.
*
*
* @param scope The scope
* @return The principal ID (account, group or user)
* @throws AuthException for any error
Expand Down Expand Up @@ -749,7 +749,7 @@ static List<Authorization> authorizations( final PolicyVersion policy, final boo
return authorizationCache.get( policy.getPolicyHash( ), new Callable<ImmutableList<Authorization>>() {
@Override
public ImmutableList<Authorization> call() throws Exception {
return ImmutableList.copyOf( ( resourcePolicy ? PolicyParser.getResourceInstance( ) : PolicyParser.getInstance( ) ).parse( policy.getPolicy( ) ).getAuthorizations( ) );
return ImmutableList.copyOf( ( resourcePolicy ? PolicyParser.getLaxResourceInstance( ) : PolicyParser.getLaxInstance( ) ).parse( policy.getPolicy( ) ).getAuthorizations( ) );
}
} );
} catch ( final ExecutionException e ) {
Expand Down

0 comments on commit 94c0a22

Please sign in to comment.