Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Asset selection in rules #61

Merged
merged 14 commits into from Aug 14, 2019
@@ -0,0 +1,13 @@
# Rotate Access Keys Regularly admin

Checks if AWS access keys are rotated regularly and are not older than a specified amount of time, i.e. 1000 days.

```ccl
User with userName=="admin" has createDate younger 90 days in all accessKeys
```

## Controls

* "IAM-02"
* "AWS 1.4"
* "BSI C5/KRY-04"
Expand Up @@ -3,7 +3,7 @@
Checks if AWS access keys are rotated regularly and are not older than a specified amount of time, i.e. 90 days.

```ccl
User has createDate after 90 days in all accessKeys
User has createDate younger 90 days in all accessKeys
```

## Controls
Expand Down
Expand Up @@ -3,7 +3,7 @@
Checks if Multi-Factor Authentication (MFA) is enabled for all users.

```ccl
condition: User has not empty mfaDevices
User has not empty mfaDevices
```

## Controls
Expand Down
Expand Up @@ -184,7 +184,7 @@ void testAccessKeyRotation() throws IOException {
FileSystemManager.getInstance()
.getPathForResource("rules/aws/iam/access-key-rotation.md"));

// user2 has an very old access key
// user2 has a very old access key
assertFalse(rule.evaluate(assets.get(USER2_ARN)).isOk());
}

Expand Down
23 changes: 17 additions & 6 deletions clouditor-engine-core/src/main/antlr/CCL.g4
Expand Up @@ -2,18 +2,25 @@ grammar CCL;

condition: assetType 'has' expression EOF;

assetType : Identifier;
assetType :
simpleAssetType |
filteredAssetType;

simpleAssetType: field;

filteredAssetType: field 'with' expression;

field : Identifier;
expression:
simpleExpression |
inExpression ;
notExpression |
inExpression;

simpleExpression:
'(' expression ')' |
notExpression |
emptyExpression |
withinExpression |
comparison;
comparison |
'(' expression ')' ;

notExpression: 'not' expression;

Expand All @@ -26,7 +33,9 @@ binaryComparison: field operator value;
timeComparison: field timeOperator (time unit | nowOperator);
timeOperator:
BeforeOperator |
AfterOperator;
AfterOperator |
YoungerOperator |
OlderOperator;
nowOperator: 'now';
time: Number;
unit:
Expand Down Expand Up @@ -66,6 +75,8 @@ ContainsOperator: 'contains';

BeforeOperator: 'before';
AfterOperator: 'after';
YoungerOperator: 'younger';
OlderOperator: 'older';

BooleanLiteral:
True |
Expand Down
Expand Up @@ -32,9 +32,7 @@
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.clouditor.assurance.ccl.CCLDeserializer;
import io.clouditor.assurance.ccl.CCLSerializer;
import io.clouditor.assurance.ccl.Condition;
import io.clouditor.assurance.ccl.*;
import io.clouditor.discovery.Asset;
import java.util.ArrayList;
import java.util.Collections;
Expand All @@ -59,6 +57,20 @@ public class Rule {
@JsonProperty private List<String> controls = new ArrayList<>();
@JsonProperty private String id;

public boolean evaluateApplicability(Asset asset) {

if (this.condition != null) {
if (this.condition.getAssetType() instanceof FilteredAssetType) {
return this.condition.getAssetType().evaluate(asset.getProperties());
}
} else if (this.conditions != null) {
if (this.conditions.get(0).getAssetType() instanceof FilteredAssetType) {
return this.conditions.get(0).getAssetType().evaluate(asset.getProperties());
}
}
return true;
}

public EvaluationResult evaluate(Asset asset) {
var eval = new EvaluationResult(this, asset.getProperties());

Expand All @@ -83,14 +95,16 @@ public void setCondition(Condition condition) {

public String getAssetType() {
// single condition
if (this.condition != null) {
return this.condition.getAssetType();
if (this.condition != null && this.condition.getAssetType() != null) {
return this.condition.getAssetType().getValue();
}

// multiple conditions
if (this.conditions != null && !this.conditions.isEmpty()) {
if (this.conditions != null
&& !this.conditions.isEmpty()
&& this.conditions.get(0).getAssetType() != null) {
// take the first one
return this.conditions.get(0).getAssetType();
return this.conditions.get(0).getAssetType().getValue();
}

// no asset type found, we cannot really use this rule then
Expand Down
Expand Up @@ -285,8 +285,13 @@ public void handle(DiscoveryResult result) {
// evaluate all rules
rulesForAsset.forEach(
rule -> {
var eval = rule.evaluate(asset);

EvaluationResult eval;
if (!rule.evaluateApplicability(asset)) {
// simply add an empty EvaluationResult
eval = new EvaluationResult(rule, asset.getProperties());
oxisto marked this conversation as resolved.
Show resolved Hide resolved
} else {
eval = rule.evaluate(asset);
}
// TODO: can we really update the asset?
asset.addEvaluationResult(eval);
if (!eval.isOk()) {
Expand Down
@@ -0,0 +1,41 @@
/*
* Copyright (c) 2016-2019, Fraunhofer AISEC. All rights reserved.
*
*
* $$\ $$\ $$\ $$\
* $$ | $$ |\__| $$ |
* $$$$$$$\ $$ | $$$$$$\ $$\ $$\ $$$$$$$ |$$\ $$$$$$\ $$$$$$\ $$$$$$\
* $$ _____|$$ |$$ __$$\ $$ | $$ |$$ __$$ |$$ |\_$$ _| $$ __$$\ $$ __$$\
* $$ / $$ |$$ / $$ |$$ | $$ |$$ / $$ |$$ | $$ | $$ / $$ |$$ | \__|
* $$ | $$ |$$ | $$ |$$ | $$ |$$ | $$ |$$ | $$ |$$\ $$ | $$ |$$ |
* \$$$$$$\ $$ |\$$$$$ |\$$$$$ |\$$$$$$ |$$ | \$$$ |\$$$$$ |$$ |
* \_______|\__| \______/ \______/ \_______|\__| \____/ \______/ \__|
*
* This file is part of Clouditor Community Edition.
*
* Clouditor Community Edition is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Clouditor Community Edition is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* long with Clouditor Community Edition. If not, see <https://www.gnu.org/licenses/>
*/

package io.clouditor.assurance.ccl;

import com.fasterxml.jackson.annotation.JsonTypeInfo;
import java.util.Map;

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "@class")
public abstract class AssetType {

public abstract boolean evaluate(Map properties);

public abstract String getValue();
}
Expand Up @@ -74,7 +74,7 @@ public Condition visitCondition(ConditionContext ctx) {
if (ctx.assetType() != null && ctx.expression() != null) {
var condition = new Condition();

condition.setAssetType(ctx.assetType().getText());
condition.setAssetType(ctx.assetType().accept(new AssetTypeListener()));
condition.setExpression(ctx.expression().accept(new ExpressionListener()));

return condition;
Expand All @@ -84,6 +84,33 @@ public Condition visitCondition(ConditionContext ctx) {
}
}

private static class AssetTypeListener extends CCLBaseVisitor<AssetType> {

@Override
public AssetType visitAssetType(CCLParser.AssetTypeContext ctx) {
if (ctx.simpleAssetType() != null) {
var simpleAsset = new SimpleAssetType();
simpleAsset.setValue(ctx.simpleAssetType().field().getText());
return simpleAsset;
} else if (ctx.filteredAssetType() != null) {
return ctx.filteredAssetType().accept(this);
}

return super.visitAssetType(ctx);
}

@Override
public AssetType visitFilteredAssetType(CCLParser.FilteredAssetTypeContext ctx) {
if (ctx.expression() != null) {
var asset = new FilteredAssetType();
asset.setValue(ctx.field().getText());
asset.setAssetExpression(ctx.expression().accept(new ExpressionListener()));
return asset;
}
return super.visitFilteredAssetType(ctx);
}
}

private static class ExpressionListener extends CCLBaseVisitor<Expression> {

@Override
Expand Down
Expand Up @@ -33,7 +33,7 @@

public class Condition {

private String assetType;
private AssetType assetType;

private Expression expression;

Expand All @@ -47,11 +47,11 @@ public void setExpression(Expression expression) {
this.expression = expression;
}

public String getAssetType() {
public AssetType getAssetType() {
return assetType;
}

public void setAssetType(String assetType) {
public void setAssetType(AssetType assetType) {
this.assetType = assetType;
}

Expand Down
@@ -0,0 +1,55 @@
/*
* Copyright (c) 2016-2019, Fraunhofer AISEC. All rights reserved.
*
*
* $$\ $$\ $$\ $$\
* $$ | $$ |\__| $$ |
* $$$$$$$\ $$ | $$$$$$\ $$\ $$\ $$$$$$$ |$$\ $$$$$$\ $$$$$$\ $$$$$$\
* $$ _____|$$ |$$ __$$\ $$ | $$ |$$ __$$ |$$ |\_$$ _| $$ __$$\ $$ __$$\
* $$ / $$ |$$ / $$ |$$ | $$ |$$ / $$ |$$ | $$ | $$ / $$ |$$ | \__|
* $$ | $$ |$$ | $$ |$$ | $$ |$$ | $$ |$$ | $$ |$$\ $$ | $$ |$$ |
* \$$$$$$\ $$ |\$$$$$ |\$$$$$ |\$$$$$$ |$$ | \$$$ |\$$$$$ |$$ |
* \_______|\__| \______/ \______/ \_______|\__| \____/ \______/ \__|
*
* This file is part of Clouditor Community Edition.
*
* Clouditor Community Edition is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Clouditor Community Edition is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* long with Clouditor Community Edition. If not, see <https://www.gnu.org/licenses/>
*/

package io.clouditor.assurance.ccl;

import java.util.Map;

public class FilteredAssetType extends AssetType {

private String value;
private Expression assetExpression;

public String getValue() {
return this.value;
}

public void setValue(String value) {
this.value = value;
}

public void setAssetExpression(Expression assetExpression) {
this.assetExpression = assetExpression;
}

@Override
public boolean evaluate(Map properties) {
return this.assetExpression.evaluate(properties);
}
}
@@ -0,0 +1,50 @@
/*
* Copyright (c) 2016-2019, Fraunhofer AISEC. All rights reserved.
*
*
* $$\ $$\ $$\ $$\
* $$ | $$ |\__| $$ |
* $$$$$$$\ $$ | $$$$$$\ $$\ $$\ $$$$$$$ |$$\ $$$$$$\ $$$$$$\ $$$$$$\
* $$ _____|$$ |$$ __$$\ $$ | $$ |$$ __$$ |$$ |\_$$ _| $$ __$$\ $$ __$$\
* $$ / $$ |$$ / $$ |$$ | $$ |$$ / $$ |$$ | $$ | $$ / $$ |$$ | \__|
* $$ | $$ |$$ | $$ |$$ | $$ |$$ | $$ |$$ | $$ |$$\ $$ | $$ |$$ |
* \$$$$$$\ $$ |\$$$$$ |\$$$$$ |\$$$$$$ |$$ | \$$$ |\$$$$$ |$$ |
* \_______|\__| \______/ \______/ \_______|\__| \____/ \______/ \__|
*
* This file is part of Clouditor Community Edition.
*
* Clouditor Community Edition is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Clouditor Community Edition is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* long with Clouditor Community Edition. If not, see <https://www.gnu.org/licenses/>
*/

package io.clouditor.assurance.ccl;

import java.util.Map;

public class SimpleAssetType extends AssetType {

private String value;

public String getValue() {
return this.value;
}

public void setValue(String value) {
this.value = value;
}

@Override
public boolean evaluate(Map properties) {
return true;
}
}