diff --git a/.github/workflows/code-formatting.yml b/.github/workflows/code-formatting.yml
new file mode 100644
index 0000000000..45897cace6
--- /dev/null
+++ b/.github/workflows/code-formatting.yml
@@ -0,0 +1,32 @@
+name: Code Formatting Check
+
+on:
+ pull_request:
+ branches: [ main ]
+ paths:
+ - '**.java'
+ - 'pom.xml'
+ - 'codestyle/**'
+
+jobs:
+ formatting-check:
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Set up JDK 11
+ uses: actions/setup-java@v4
+ with:
+ java-version: '11'
+ distribution: 'corretto'
+
+ - name: Cache Maven dependencies
+ uses: actions/cache@v3
+ with:
+ path: ~/.m2
+ key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
+ restore-keys: ${{ runner.os }}-m2
+
+ - name: Check code formatting
+ run: mvn spotless:check
diff --git a/codestyle/eclipse-formatter.xml b/codestyle/eclipse-formatter.xml
new file mode 100644
index 0000000000..7718461bd7
--- /dev/null
+++ b/codestyle/eclipse-formatter.xml
@@ -0,0 +1,256 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pom.xml b/pom.xml
index bd27736529..ab1be16d1a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -445,34 +445,6 @@
-
- maven-checkstyle-plugin
- 3.1.0
-
-
- com.puppycrawl.tools
- checkstyle
- 8.29
-
-
-
- true
- codestyle/checkstyle.xml
- warning
- 0
- **/awssdk/**, **/eventstream/**, **/vendored/**
- ${skipTests}
-
-
-
- validate
- validate
-
- check
-
-
-
- maven-surefire-plugin3.0.0-M7
@@ -846,6 +818,19 @@
+
+ com.diffplug.spotless
+ spotless-maven-plugin
+ 2.40.0
+
+
+
+ codestyle/eclipse-formatter.xml
+
+
+
+
+
diff --git a/src/main/java/com/aws/greengrass/authorization/AuthorizationHandler.java b/src/main/java/com/aws/greengrass/authorization/AuthorizationHandler.java
index 49521d4675..6c93302d76 100644
--- a/src/main/java/com/aws/greengrass/authorization/AuthorizationHandler.java
+++ b/src/main/java/com/aws/greengrass/authorization/AuthorizationHandler.java
@@ -65,17 +65,15 @@
import static software.amazon.awssdk.aws.greengrass.GreengrassCoreIPCServiceModel.STOP_COMPONENT;
/**
- * Main module which is responsible for handling AuthZ for Greengrass. This only manages
- * the AuthZ configuration and performs lookups based on the config. Config is just a copy of
- * customer config and this module does not try to optimize storage. For instance,
- * if customer specifies same policy twice, we treat and store them separately. Components are
- * identified by their service identifiers (component names) and operation/resources are assumed to be
- * opaque strings. They are not treated as confidential and it should be the responsibility
- * of the caller to use proxy identifiers for confidential data. Implementation optimizes for fast lookups
- * and not for storage.
+ * Main module which is responsible for handling AuthZ for Greengrass. This only manages the AuthZ configuration and
+ * performs lookups based on the config. Config is just a copy of customer config and this module does not try to
+ * optimize storage. For instance, if customer specifies same policy twice, we treat and store them separately.
+ * Components are identified by their service identifiers (component names) and operation/resources are assumed to be
+ * opaque strings. They are not treated as confidential and it should be the responsibility of the caller to use proxy
+ * identifiers for confidential data. Implementation optimizes for fast lookups and not for storage.
*/
@Singleton
-public class AuthorizationHandler {
+public class AuthorizationHandler {
public static final String ANY_REGEX = "*";
public static final String SECRETS_MANAGER_SERVICE_NAME = "aws.greengrass.SecretManager";
public static final String SHADOW_MANAGER_SERVICE_NAME = "aws.greengrass.ShadowManager";
@@ -83,14 +81,13 @@ public class AuthorizationHandler {
private static final String CLI_SERVICE_NAME = "aws.greengrass.Cli";
public enum ResourceLookupPolicy {
- STANDARD,
- MQTT_STYLE
+ STANDARD, MQTT_STYLE
}
private static final Logger logger = LogManager.getLogger(AuthorizationHandler.class);
private final ConcurrentHashMap> componentToOperationsMap = new ConcurrentHashMap<>();
- private final ConcurrentHashMap>
- componentToAuthZConfig = new ConcurrentHashMap<>();
+ private final ConcurrentHashMap> componentToAuthZConfig =
+ new ConcurrentHashMap<>();
private final Kernel kernel;
private final AuthorizationModule authModule;
@@ -104,40 +101,35 @@ public enum ResourceLookupPolicy {
* @param policyParser for parsing a given policy ACL
*/
@Inject
- public AuthorizationHandler(Kernel kernel, AuthorizationModule authModule,
- AuthorizationPolicyParser policyParser) {
+ public AuthorizationHandler(Kernel kernel, AuthorizationModule authModule, AuthorizationPolicyParser policyParser) {
this.kernel = kernel;
this.authModule = authModule;
// Adding TES component and operation before it's default policies are fetched
- componentToOperationsMap.put(TOKEN_EXCHANGE_SERVICE_TOPICS, new HashSet<>(
- Collections.singletonList(AUTHZ_TES_OPERATION)));
- componentToOperationsMap.put(PUB_SUB_SERVICE_NAME, new HashSet<>(Arrays.asList(PUBLISH_TO_TOPIC,
- SUBSCRIBE_TO_TOPIC, ANY_REGEX)));
- componentToOperationsMap.put(MQTT_PROXY_SERVICE_NAME, new HashSet<>(Arrays.asList(PUBLISH_TO_IOT_CORE,
- SUBSCRIBE_TO_IOT_CORE, ANY_REGEX)));
- componentToOperationsMap.put(SECRETS_MANAGER_SERVICE_NAME, new HashSet<>(Arrays.asList(GET_SECRET_VALUE,
- ANY_REGEX)));
+ componentToOperationsMap.put(TOKEN_EXCHANGE_SERVICE_TOPICS,
+ new HashSet<>(Collections.singletonList(AUTHZ_TES_OPERATION)));
+ componentToOperationsMap.put(PUB_SUB_SERVICE_NAME,
+ new HashSet<>(Arrays.asList(PUBLISH_TO_TOPIC, SUBSCRIBE_TO_TOPIC, ANY_REGEX)));
+ componentToOperationsMap.put(MQTT_PROXY_SERVICE_NAME,
+ new HashSet<>(Arrays.asList(PUBLISH_TO_IOT_CORE, SUBSCRIBE_TO_IOT_CORE, ANY_REGEX)));
+ componentToOperationsMap.put(SECRETS_MANAGER_SERVICE_NAME,
+ new HashSet<>(Arrays.asList(GET_SECRET_VALUE, ANY_REGEX)));
componentToOperationsMap.put(SHADOW_MANAGER_SERVICE_NAME, new HashSet<>(Arrays.asList(GET_THING_SHADOW,
UPDATE_THING_SHADOW, DELETE_THING_SHADOW, LIST_NAMED_SHADOWS_FOR_THING, ANY_REGEX)));
- componentToOperationsMap.put(LIFECYCLE_SERVICE_NAME, new HashSet<>(Arrays.asList(PAUSE_COMPONENT,
- RESUME_COMPONENT, ANY_REGEX)));
+ componentToOperationsMap.put(LIFECYCLE_SERVICE_NAME,
+ new HashSet<>(Arrays.asList(PAUSE_COMPONENT, RESUME_COMPONENT, ANY_REGEX)));
componentToOperationsMap.put(CLIENT_DEVICE_AUTH_SERVICE_NAME,
- new HashSet<>(Arrays.asList(SUBSCRIBE_TO_CERTIFICATE_UPDATES,
- VERIFY_CLIENT_DEVICE_IDENTITY,
- GET_CLIENT_DEVICE_AUTH_TOKEN,
- AUTHORIZE_CLIENT_DEVICE_ACTION,
- ANY_REGEX)));
- componentToOperationsMap.put(CLI_SERVICE_NAME, new HashSet<>(Arrays.asList(GET_COMPONENT_DETAILS,
- LIST_COMPONENTS, RESTART_COMPONENT,
- STOP_COMPONENT, CREATE_LOCAL_DEPLOYMENT,
- GET_LOCAL_DEPLOYMENT_STATUS, LIST_LOCAL_DEPLOYMENTS,
- CREATE_DEBUG_PASSWORD, ANY_REGEX)));
+ new HashSet<>(Arrays.asList(SUBSCRIBE_TO_CERTIFICATE_UPDATES, VERIFY_CLIENT_DEVICE_IDENTITY,
+ GET_CLIENT_DEVICE_AUTH_TOKEN, AUTHORIZE_CLIENT_DEVICE_ACTION, ANY_REGEX)));
+ componentToOperationsMap.put(CLI_SERVICE_NAME,
+ new HashSet<>(Arrays.asList(GET_COMPONENT_DETAILS, LIST_COMPONENTS, RESTART_COMPONENT, STOP_COMPONENT,
+ CREATE_LOCAL_DEPLOYMENT, GET_LOCAL_DEPLOYMENT_STATUS, LIST_LOCAL_DEPLOYMENTS,
+ CREATE_DEBUG_PASSWORD, ANY_REGEX)));
componentToOperationsMap.put(PUT_COMPONENT_METRIC_SERVICE_NAME,
new HashSet<>(Arrays.asList(PUT_COMPONENT_METRIC, ANY_REGEX)));
- Map> componentNameToPolicies = policyParser.parseAllAuthorizationPolicies(
- kernel);
- //Load default policies
+ Map> componentNameToPolicies =
+ policyParser.parseAllAuthorizationPolicies(kernel);
+ // Load default policies
componentNameToPolicies.putAll(getDefaultPolicies());
for (Map.Entry> acl : componentNameToPolicies.entrySet()) {
@@ -153,19 +145,20 @@ public AuthorizationHandler(Kernel kernel, AuthorizationModule authModule,
return false;
}
- //If there is a childChanged event, it has to be the 'accessControl' Topic that has bubbled up
- //If there is a childRemoved event, it could be the component is removed, or either the
- //'accessControl' Topic or/the 'parameters' Topics that has bubbled up, so we need to handle and
- //filter out all other WhatHappeneds
+ // If there is a childChanged event, it has to be the 'accessControl' Topic that has bubbled up
+ // If there is a childRemoved event, it could be the component is removed, or either the
+ // 'accessControl' Topic or/the 'parameters' Topics that has bubbled up, so we need to handle and
+ // filter out all other WhatHappeneds
if (WhatHappened.childRemoved.equals(why) || WhatHappened.removed.equals(why)) {
// Either a service or a parameter block or acl subkey
- if (!newv.parent.getName().equals(SERVICES_NAMESPACE_TOPIC) && !newv.getName()
- .equals(CONFIGURATION_CONFIG_KEY) && !newv.getName().equals(ACCESS_CONTROL_NAMESPACE_TOPIC)
+ if (!newv.parent.getName().equals(SERVICES_NAMESPACE_TOPIC)
+ && !newv.getName().equals(CONFIGURATION_CONFIG_KEY)
+ && !newv.getName().equals(ACCESS_CONTROL_NAMESPACE_TOPIC)
&& !newv.childOf(ACCESS_CONTROL_NAMESPACE_TOPIC)) {
return true;
}
- } else if (!newv.childOf(ACCESS_CONTROL_NAMESPACE_TOPIC) && !newv.getName()
- .equals(ACCESS_CONTROL_NAMESPACE_TOPIC)) {
+ } else if (!newv.childOf(ACCESS_CONTROL_NAMESPACE_TOPIC)
+ && !newv.getName().equals(ACCESS_CONTROL_NAMESPACE_TOPIC)) {
// for all other WhatHappened cases we only care about access control change
return true;
}
@@ -180,18 +173,18 @@ public AuthorizationHandler(Kernel kernel, AuthorizationModule authModule,
reloadedPolicies.putAll(getDefaultPolicies());
try (LockScope scope = LockScope.lock(rwLock.writeLock())) {
- for (Map.Entry> primaryPolicyList
- : componentToAuthZConfig.entrySet()) {
+ for (Map.Entry> primaryPolicyList : componentToAuthZConfig
+ .entrySet()) {
String policyType = primaryPolicyList.getKey();
if (!reloadedPolicies.containsKey(policyType)) {
- //If the policyType already exists and was not reparsed correctly and/or removed from
- //the newly parsed list, delete it from our store since it is now an unwanted relic
+ // If the policyType already exists and was not reparsed correctly and/or removed from
+ // the newly parsed list, delete it from our store since it is now an unwanted relic
componentToAuthZConfig.remove(policyType);
authModule.deletePermissionsWithDestination(policyType);
}
}
- //Now we reload the policies that reflect the current state of the Nucleus config
+ // Now we reload the policies that reflect the current state of the Nucleus config
for (Map.Entry> acl : reloadedPolicies.entrySet()) {
this.loadAuthorizationPolicies(acl.getKey(), acl.getValue(), true);
}
@@ -200,13 +193,12 @@ public AuthorizationHandler(Kernel kernel, AuthorizationModule authModule,
}
/**
- * Check if the combination of destination, principal, operation and resource is allowed.
- * A scenario where this method is called is for a request which originates from {@code principal}
- * component destined for {@code destination} component, which needs access to {@code resource}
- * using API {@code operation}.
+ * Check if the combination of destination, principal, operation and resource is allowed. A scenario where this
+ * method is called is for a request which originates from {@code principal} component destined for
+ * {@code destination} component, which needs access to {@code resource} using API {@code operation}.
*
* @param destination Destination component which is being accessed.
- * @param permission container for principal, operation and resource.
+ * @param permission container for principal, operation and resource.
* @param resourceLookupPolicy whether to match MQTT wildcards or not.
* @return whether the input combination is a valid flow.
* @throws AuthorizationException when flow is not authorized.
@@ -222,10 +214,15 @@ public boolean isAuthorized(String destination, Permission permission, ResourceL
// Lookup all possible allow configurations starting from most specific to least
// This helps for access logs, as customer can figure out which policy is being hit.
String[][] combinations = {
- {destination, principal, operation, resource},
- {destination, principal, ANY_REGEX, resource},
- {destination, ANY_REGEX, operation, resource},
- {destination, ANY_REGEX, ANY_REGEX, resource},
+ {
+ destination, principal, operation, resource
+ }, {
+ destination, principal, ANY_REGEX, resource
+ }, {
+ destination, ANY_REGEX, operation, resource
+ }, {
+ destination, ANY_REGEX, ANY_REGEX, resource
+ },
};
try (LockScope scope = LockScope.lock(rwLock.readLock())) {
for (String[] combination : combinations) {
@@ -234,21 +231,17 @@ public boolean isAuthorized(String destination, Permission permission, ResourceL
.principal(combination[1])
.operation(combination[2])
.resource(combination[3])
- .build(), resourceLookupPolicy)) {
- logger.atDebug().log("Hit policy with principal {}, operation {}, resource {}",
- combination[1],
- combination[2],
- combination[3]);
+ .build(),
+ resourceLookupPolicy)) {
+ logger.atDebug()
+ .log("Hit policy with principal {}, operation {}, resource {}", combination[1],
+ combination[2], combination[3]);
return true;
}
}
}
- throw new AuthorizationException(
- String.format("Principal %s is not authorized to perform %s:%s on resource %s",
- principal,
- destination,
- operation,
- resource));
+ throw new AuthorizationException(String.format("Principal %s is not authorized to perform %s:%s on resource %s",
+ principal, destination, operation, resource));
}
public boolean isAuthorized(String destination, Permission permission) throws AuthorizationException {
@@ -256,12 +249,12 @@ public boolean isAuthorized(String destination, Permission permission) throws Au
}
/**
- * Get allowed resources for the combination of destination, principal and operation.
- * Also returns resources covered by permissions with * operation/principal.
+ * Get allowed resources for the combination of destination, principal and operation. Also returns resources covered
+ * by permissions with * operation/principal.
*
* @param destination destination
- * @param principal principal (cannot be *)
- * @param operation operation (cannot be *)
+ * @param principal principal (cannot be *)
+ * @param operation operation (cannot be *)
* @return list of allowed resources
* @throws AuthorizationException when arguments are invalid
*/
@@ -278,18 +271,16 @@ public Set getAuthorizedResources(String destination, @NonNull String pr
}
/**
- * Register a component with AuthZ module. This registers an Greengrass component with authorization module.
- * This is required to register list of operations supported by a component especially for 3P component
- * in future, whose operations might not be known at bootstrap.
- * Operations are identifiers which the components intend to match for incoming requests by calling
- * {@link #isAuthorized(String, Permission)} isAuthorized} method.
+ * Register a component with AuthZ module. This registers an Greengrass component with authorization module. This is
+ * required to register list of operations supported by a component especially for 3P component in future, whose
+ * operations might not be known at bootstrap. Operations are identifiers which the components intend to match for
+ * incoming requests by calling {@link #isAuthorized(String, Permission)} isAuthorized} method.
*
* @param componentName Name of the component to be registered.
- * @param operations Set of operations the component needs to register with AuthZ.
+ * @param operations Set of operations the component needs to register with AuthZ.
* @throws AuthorizationException If component is already registered.
*/
- public void registerComponent(String componentName, Set operations)
- throws AuthorizationException {
+ public void registerComponent(String componentName, Set operations) throws AuthorizationException {
if (Utils.isEmpty(operations) || Utils.isEmpty(componentName)) {
throw new AuthorizationException("Invalid arguments for registerComponent()");
}
@@ -299,16 +290,14 @@ public void registerComponent(String componentName, Set operations)
/**
* Loads authZ policies for a single component for future auth lookups. The policies should not have confidential
- * values. This method assumes that the component names for principal and destination,
- * the operations and resources must not be secret and can be logged or shared if required.
- * If the isUpdate flag is specified, this method will clear the existing policies for a component before
- * refreshing with the updated list.
+ * values. This method assumes that the component names for principal and destination, the operations and resources
+ * must not be secret and can be logged or shared if required. If the isUpdate flag is specified, this method will
+ * clear the existing policies for a component before refreshing with the updated list.
*
* @param componentName Destination component which intends to supply auth policies
- * @param policies List of policies. All policies are treated as separate
- * and no merging or joins happen. Duplicated policies would result in duplicated
- * permissions but would not impact functionality.
- * @param isUpdate If this load request is to update existing policies for a component.
+ * @param policies List of policies. All policies are treated as separate and no merging or joins happen. Duplicated
+ * policies would result in duplicated permissions but would not impact functionality.
+ * @param isUpdate If this load request is to update existing policies for a component.
*/
public void loadAuthorizationPolicies(String componentName, List policies, boolean isUpdate) {
if (policies == null) {
@@ -318,16 +307,17 @@ public void loadAuthorizationPolicies(String componentName, List operations = policy.getOperations();
if (Utils.isEmpty(operations)) {
- throw new AuthorizationException("Malformed policy with invalid/empty operations: "
- + policy.getPolicyId());
+ throw new AuthorizationException("Malformed policy with invalid/empty operations: " + policy.getPolicyId());
}
Set supportedOps = componentToOperationsMap.get(componentName);
@@ -400,12 +391,11 @@ private void isComponentRegistered(String componentName) throws AuthorizationExc
}
}
- private void isOperationValid(String componentName, String operation)
- throws AuthorizationException {
+ private void isOperationValid(String componentName, String operation) throws AuthorizationException {
isComponentRegistered(componentName);
if (!componentToOperationsMap.get(componentName).contains(operation)) {
- throw new AuthorizationException(String.format("Component %s not registered for operation %s",
- componentName, operation));
+ throw new AuthorizationException(
+ String.format("Component %s not registered for operation %s", componentName, operation));
}
}
@@ -422,8 +412,10 @@ private void validatePrincipals(AuthorizationPolicy policy) throws Authorization
throw new AuthorizationException("Malformed policy with invalid/empty principal: " + policy.getPolicyId());
}
// check if principal is a valid EG component
- List unknownSources = principals.stream().filter(s -> !s.equals(ANY_REGEX)).filter(s ->
- kernel.findServiceTopic(s) == null).collect(Collectors.toList());
+ List unknownSources = principals.stream()
+ .filter(s -> !s.equals(ANY_REGEX))
+ .filter(s -> kernel.findServiceTopic(s) == null)
+ .collect(Collectors.toList());
if (!unknownSources.isEmpty()) {
throw new AuthorizationException(
@@ -431,11 +423,8 @@ private void validatePrincipals(AuthorizationPolicy policy) throws Authorization
}
}
- private void addPermission(String destination,
- String policyId,
- Set principals,
- Set operations,
- Set resources) throws AuthorizationException {
+ private void addPermission(String destination, String policyId, Set principals, Set operations,
+ Set resources) throws AuthorizationException {
// Method assumes that all inputs are valid now
for (String principal : principals) {
for (String operation : operations) {
@@ -452,14 +441,15 @@ private void addPermission(String destination,
.resource(resource)
.build());
} catch (AuthorizationException e) {
- logger.atError("load-authorization-config-add-resource-error").setCause(e)
+ logger.atError("load-authorization-config-add-resource-error")
+ .setCause(e)
.kv("policyId", policyId)
.kv("component", principal)
.kv("operation", operation)
.kv("IPC service", destination)
.kv("resource", resource)
- .log("Error while adding permission for component {} "
- + "to IPC Service {}", principal, destination);
+ .log("Error while adding permission for component {} " + "to IPC Service {}",
+ principal, destination);
}
}
}
@@ -469,15 +459,18 @@ private void addPermission(String destination,
private List getDefaultPolicyForService(String serviceName) {
String defaultPolicyDesc = "Default policy for " + serviceName;
- return Collections.singletonList(AuthorizationPolicy.builder().policyId(UUID.randomUUID().toString())
- .policyDescription(defaultPolicyDesc).principals(new HashSet<>(Collections.singletonList("*")))
- .operations(new HashSet<>(Collections.singletonList(serviceName))).build());
+ return Collections.singletonList(AuthorizationPolicy.builder()
+ .policyId(UUID.randomUUID().toString())
+ .policyDescription(defaultPolicyDesc)
+ .principals(new HashSet<>(Collections.singletonList("*")))
+ .operations(new HashSet<>(Collections.singletonList(serviceName)))
+ .build());
}
private Map> getDefaultPolicies() {
Map> allDefaultPolicies = new HashMap<>();
- //Create the default policy for TES
+ // Create the default policy for TES
allDefaultPolicies.put(TOKEN_EXCHANGE_SERVICE_TOPICS, getDefaultPolicyForService(AUTHZ_TES_OPERATION));
return allDefaultPolicies;
diff --git a/src/main/java/com/aws/greengrass/authorization/AuthorizationIPCAgent.java b/src/main/java/com/aws/greengrass/authorization/AuthorizationIPCAgent.java
index 68b9121cbe..523ac8c64f 100644
--- a/src/main/java/com/aws/greengrass/authorization/AuthorizationIPCAgent.java
+++ b/src/main/java/com/aws/greengrass/authorization/AuthorizationIPCAgent.java
@@ -44,7 +44,8 @@ public ValidateAuthorizationTokenOperationHandler getValidateAuthorizationTokenO
@SuppressWarnings("PMD.PreserveStackTrace")
class ValidateAuthorizationTokenOperationHandler
- extends GeneratedAbstractValidateAuthorizationTokenOperationHandler {
+ extends
+ GeneratedAbstractValidateAuthorizationTokenOperationHandler {
private final String serviceName;
protected ValidateAuthorizationTokenOperationHandler(OperationContinuationHandlerContext context) {
@@ -65,8 +66,9 @@ public void handleStreamEvent(EventStreamJsonMessage streamRequestEvent) {
@Override
public ValidateAuthorizationTokenResponse handleRequest(ValidateAuthorizationTokenRequest request) {
if (!AUTHORIZED_COMPONENTS.contains(serviceName)) {
- logger.atDebug("service-unauthorized-error").log("{} is not authorized to perform {}",
- serviceName, this.getOperationModelContext().getOperationName());
+ logger.atDebug("service-unauthorized-error")
+ .log("{} is not authorized to perform {}", serviceName,
+ this.getOperationModelContext().getOperationName());
throw new UnauthorizedError(String.format("%s is not authorized to perform %s", serviceName,
this.getOperationModelContext().getOperationName()));
}
@@ -74,12 +76,14 @@ public ValidateAuthorizationTokenResponse handleRequest(ValidateAuthorizationTok
try {
authenticationHandler.doAuthentication(request.getToken());
response.setIsValid(true);
- logger.atDebug("authorization-validated").log("Authorization validated for {} for {}",
- serviceName, this.getOperationModelContext().getOperationName());
+ logger.atDebug("authorization-validated")
+ .log("Authorization validated for {} for {}", serviceName,
+ this.getOperationModelContext().getOperationName());
return response;
} catch (UnauthenticatedException e) {
- logger.atDebug("invalid-token-error").log("Invalid token used when trying to authorize {} "
- + "to perform {}", serviceName, this.getOperationModelContext().getOperationName());
+ logger.atDebug("invalid-token-error")
+ .log("Invalid token used when trying to authorize {} " + "to perform {}", serviceName,
+ this.getOperationModelContext().getOperationName());
throw new InvalidTokenError(e.getMessage());
}
}
diff --git a/src/main/java/com/aws/greengrass/authorization/AuthorizationModule.java b/src/main/java/com/aws/greengrass/authorization/AuthorizationModule.java
index fc0a69f8e9..c8d660949d 100644
--- a/src/main/java/com/aws/greengrass/authorization/AuthorizationModule.java
+++ b/src/main/java/com/aws/greengrass/authorization/AuthorizationModule.java
@@ -23,42 +23,43 @@
import static com.aws.greengrass.authorization.WildcardTrie.wildcardChar;
/**
- * Simple permission table which stores permissions. A permission is a
- * 4 value set of destination,principal,operation,resource.
+ * Simple permission table which stores permissions. A permission is a 4 value set of
+ * destination,principal,operation,resource.
*/
public class AuthorizationModule {
// Destination, Principal, Operation, Resource
- Map>> resourceAuthZCompleteMap =
- new DefaultConcurrentHashMap<>(() -> new DefaultConcurrentHashMap<>(() ->
- new DefaultConcurrentHashMap<>(WildcardTrie::new)));
+ Map>> resourceAuthZCompleteMap = new DefaultConcurrentHashMap<>(
+ () -> new DefaultConcurrentHashMap<>(() -> new DefaultConcurrentHashMap<>(WildcardTrie::new)));
Map>>> rawResourceList = new DefaultConcurrentHashMap<>(
() -> new DefaultConcurrentHashMap<>(() -> new DefaultConcurrentHashMap<>(CopyOnWriteArraySet::new)));
/**
* Add permission for the given input set.
+ *
* @param destination destination entity
* @param permission set of principal, operation, resource.
* @throws AuthorizationException when arguments are invalid
*/
public void addPermission(String destination, Permission permission) throws AuthorizationException {
// resource is allowed to be null
- if (Utils.isEmpty(permission.getPrincipal())
- || Utils.isEmpty(destination)
+ if (Utils.isEmpty(permission.getPrincipal()) || Utils.isEmpty(destination)
|| Utils.isEmpty(permission.getOperation())) {
throw new AuthorizationException("Invalid arguments");
}
String resource = permission.getResource();
validateResource(resource);
- resourceAuthZCompleteMap.get(destination).get(permission.getPrincipal()).get(permission.getOperation()).add(
- resource);
- rawResourceList.get(destination).get(permission.getPrincipal()).get(permission.getOperation()).add(
- resource);
+ resourceAuthZCompleteMap.get(destination)
+ .get(permission.getPrincipal())
+ .get(permission.getOperation())
+ .add(resource);
+ rawResourceList.get(destination).get(permission.getPrincipal()).get(permission.getOperation()).add(resource);
}
/**
- * Only allow '?' if it's escaped. You can only escape special characters ('*', '$', '?').
- * Any occurrence of '${' is only valid if it holds a single valid special character ('*', '$', '?') inside it
- * and ends with '}'. (eg: "${*}" is valid, "${c}" is invalid, "${c" is invalid, ${*bc} is invalid)
+ * Only allow '?' if it's escaped. You can only escape special characters ('*', '$', '?'). Any occurrence of '${' is
+ * only valid if it holds a single valid special character ('*', '$', '?') inside it and ends with '}'. (eg: "${*}"
+ * is valid, "${c}" is invalid, "${c" is invalid, ${*bc} is invalid)
+ *
* @param resource resource to be validated
*/
private void validateResource(String resource) throws AuthorizationException {
@@ -75,12 +76,12 @@ private void validateResource(String resource) throws AuthorizationException {
if (currentChar == escapeChar && i + 1 < length && resource.charAt(i + 1) == '{') {
char actualChar = getActualChar(resource.substring(i));
if (actualChar == nullChar) {
- throw new AuthorizationException("Resource contains an invalid escape sequence. "
- + "You can use ${*}, ${$}, or ${?}");
+ throw new AuthorizationException(
+ "Resource contains an invalid escape sequence. " + "You can use ${*}, ${$}, or ${?}");
}
if (!isSpecialChar(actualChar)) {
- throw new AuthorizationException("Resource contains an invalid escape "
- + "sequence: ${" + actualChar + "}. You can use ${*}, ${$}, or ${?}");
+ throw new AuthorizationException("Resource contains an invalid escape " + "sequence: ${"
+ + actualChar + "}. You can use ${*}, ${$}, or ${?}");
}
// skip next 3 characters as they are accounted for in escape sequence
i = i + 3;
@@ -96,9 +97,9 @@ boolean isSpecialChar(char actualChar) {
return actualChar == wildcardChar || actualChar == escapeChar || actualChar == singleCharWildcard;
}
-
/**
* Clear the permission list for a given destination. This is used when updating policies for a component.
+ *
* @param destination destination value
*/
public void deletePermissionsWithDestination(String destination) {
@@ -108,6 +109,7 @@ public void deletePermissionsWithDestination(String destination) {
/**
* Check if the combination of destination,principal,operation,resource exists in the table.
+ *
* @param destination destination value
* @param permission set of principal, operation and resource.
* @param resourceLookupPolicy whether to match MQTT wildcards or not.
@@ -117,8 +119,7 @@ public void deletePermissionsWithDestination(String destination) {
@SuppressWarnings("PMD.AvoidDeeplyNestedIfStmts")
public boolean isPresent(String destination, Permission permission, ResourceLookupPolicy resourceLookupPolicy)
throws AuthorizationException {
- if (Utils.isEmpty(permission.getPrincipal())
- || Utils.isEmpty(destination)
+ if (Utils.isEmpty(permission.getPrincipal()) || Utils.isEmpty(destination)
|| Utils.isEmpty(permission.getOperation())) {
throw new AuthorizationException("Invalid arguments");
}
@@ -132,8 +133,8 @@ public boolean isPresent(String destination, Permission permission, ResourceLook
if (destMap.containsKey(permission.getPrincipal())) {
Map principalMap = destMap.get(permission.getPrincipal());
if (principalMap.containsKey(permission.getOperation())) {
- return principalMap.get(permission.getOperation()).matches(permission.getResource(),
- resourceLookupPolicy);
+ return principalMap.get(permission.getOperation())
+ .matches(permission.getResource(), resourceLookupPolicy);
}
}
}
@@ -145,19 +146,19 @@ public boolean isPresent(String destination, Permission permission) throws Autho
}
/**
- * Get resources for combination of destination, principal and operation.
- * Also returns resources covered by permissions with * operation/principal.
+ * Get resources for combination of destination, principal and operation. Also returns resources covered by
+ * permissions with * operation/principal.
*
* @param destination destination
- * @param principal principal (cannot be *)
- * @param operation operation (cannot be *)
+ * @param principal principal (cannot be *)
+ * @param operation operation (cannot be *)
* @return list of allowed resources
* @throws AuthorizationException when arguments are invalid
*/
public Set getResources(String destination, String principal, String operation)
throws AuthorizationException {
- if (Utils.isEmpty(destination) || Utils.isEmpty(principal) || Utils.isEmpty(operation) || principal
- .equals(ANY_REGEX) || operation.equals(ANY_REGEX)) {
+ if (Utils.isEmpty(destination) || Utils.isEmpty(principal) || Utils.isEmpty(operation)
+ || principal.equals(ANY_REGEX) || operation.equals(ANY_REGEX)) {
throw new AuthorizationException("Invalid arguments");
}
diff --git a/src/main/java/com/aws/greengrass/authorization/AuthorizationPolicy.java b/src/main/java/com/aws/greengrass/authorization/AuthorizationPolicy.java
index f5f86a2636..27b511a1a5 100644
--- a/src/main/java/com/aws/greengrass/authorization/AuthorizationPolicy.java
+++ b/src/main/java/com/aws/greengrass/authorization/AuthorizationPolicy.java
@@ -21,10 +21,13 @@
@AllArgsConstructor
@NoArgsConstructor
public class AuthorizationPolicy implements Comparable {
- @NonNull String policyId;
+ @NonNull
+ String policyId;
String policyDescription;
- @NonNull Set principals;
- @NonNull Set operations;
+ @NonNull
+ Set principals;
+ @NonNull
+ Set operations;
Set resources;
@Override
diff --git a/src/main/java/com/aws/greengrass/authorization/AuthorizationPolicyConfig.java b/src/main/java/com/aws/greengrass/authorization/AuthorizationPolicyConfig.java
index 62293e23ee..2b5dfaa0bb 100644
--- a/src/main/java/com/aws/greengrass/authorization/AuthorizationPolicyConfig.java
+++ b/src/main/java/com/aws/greengrass/authorization/AuthorizationPolicyConfig.java
@@ -21,7 +21,10 @@
@AllArgsConstructor
@NoArgsConstructor
public class AuthorizationPolicyConfig {
- @NonNull String policyDescription;
- @NonNull Set operations;
- @NonNull Set resources;
+ @NonNull
+ String policyDescription;
+ @NonNull
+ Set operations;
+ @NonNull
+ Set resources;
}
diff --git a/src/main/java/com/aws/greengrass/authorization/AuthorizationPolicyParser.java b/src/main/java/com/aws/greengrass/authorization/AuthorizationPolicyParser.java
index 5d01b6c18c..30862d16dd 100644
--- a/src/main/java/com/aws/greengrass/authorization/AuthorizationPolicyParser.java
+++ b/src/main/java/com/aws/greengrass/authorization/AuthorizationPolicyParser.java
@@ -32,11 +32,11 @@ public final class AuthorizationPolicyParser {
private static final Logger logger = LogManager.getLogger(AuthorizationPolicyParser.class);
private static final ObjectMapper OBJECT_MAPPER =
JsonMapper.builder().configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true).build();
+
/**
- * Given a kernel object, construct and return a map of AuthorizationPolicy objects that may exist,
- * grouped into lists of the same destination component.
- * This is used only upon kernel startup, to initialize all policies.
- * Never returns null.
+ * Given a kernel object, construct and return a map of AuthorizationPolicy objects that may exist, grouped into
+ * lists of the same destination component. This is used only upon kernel startup, to initialize all policies. Never
+ * returns null.
*
* @param kernel Kernel
* @return {@Map} of {@String} keys and {@List} of {@AuthorizationPolicy}'s as values"
@@ -52,7 +52,7 @@ public Map> parseAllAuthorizationPolicies(Kern
return primaryAuthorizationPolicyMap;
}
- //For each component
+ // For each component
for (Node service : allServices) {
if (service == null) {
@@ -66,24 +66,24 @@ public Map> parseAllAuthorizationPolicies(Kern
Topics serviceConfig = (Topics) service;
String componentName = Kernel.findServiceForNode(serviceConfig);
- Node accessControlMapTopic = serviceConfig
- .findNode(CONFIGURATION_CONFIG_KEY, ACCESS_CONTROL_NAMESPACE_TOPIC);
+ Node accessControlMapTopic =
+ serviceConfig.findNode(CONFIGURATION_CONFIG_KEY, ACCESS_CONTROL_NAMESPACE_TOPIC);
if (accessControlMapTopic == null) {
continue;
}
// Retrieve all policies, mapped to each policy type
- Map> componentAuthorizationPolicyMap = parseAllPoliciesForComponent(
- accessControlMapTopic, componentName);
+ Map> componentAuthorizationPolicyMap =
+ parseAllPoliciesForComponent(accessControlMapTopic, componentName);
// For each policy type (e.g. aws.greengrass.ipc.pubsub)
- for (Map.Entry> policyTypeList :
- componentAuthorizationPolicyMap.entrySet()) {
+ for (Map.Entry> policyTypeList : componentAuthorizationPolicyMap
+ .entrySet()) {
String policyType = policyTypeList.getKey();
List policyList = policyTypeList.getValue();
- //If multiple components have policies for the same policy type
+ // If multiple components have policies for the same policy type
primaryAuthorizationPolicyMap.computeIfAbsent(policyType, k -> new ArrayList<>()).addAll(policyList);
}
}
@@ -92,47 +92,27 @@ public Map> parseAllAuthorizationPolicies(Kern
/**
* Given a accessControlMapTopic Topic, construct and return a map of AuthorizationPolicy objects that may exist
- * only for that component config, grouped into lists of the same destination component.
- * Never returns null.
+ * only for that component config, grouped into lists of the same destination component. Never returns null.
*
* @param accessControlTopic Topic access control configuration
* @param sourceComponent String the source component which has the access control config
- * @return {@Map} of {@String} keys and {@List} of {@AuthorizationPolicy}'s as values"
+ * @return {@Map} of {@String} keys and {@List} of {@AuthorizationPolicy}'s as values"
*/
private Map> parseAllPoliciesForComponent(Node accessControlTopic,
- String sourceComponent) {
+ String sourceComponent) {
Map> authorizationPolicyMap = new HashMap<>();
Map> accessControlMap = new HashMap<>();
/*
- Parse the config which is in the following format where first level key denotes the destination
- component principal and second level denotes the policy object keyed by a unique ID
- accessControl:
- aws.greengrass.ipc.pubsub:
- policyId1:
- policyDescription: access to pubsub topics 1
- operations:
- - publish
- - subscribe
- resources:
- - /topic/1/#
- - /longer/topic/example/
- policyId2:
- policyDescription: access to pubsub topics 2
- operations:
- - publish
- resources:
- - /publishOnlyTopic
- aws.greengrass.secretsManager:
- policyId3:
- policyDescription: access to secrets
- operations:
- - getsecret
- resources:
- - secret1
- */
+ * Parse the config which is in the following format where first level key denotes the destination component
+ * principal and second level denotes the policy object keyed by a unique ID accessControl:
+ * aws.greengrass.ipc.pubsub: policyId1: policyDescription: access to pubsub topics 1 operations: - publish -
+ * subscribe resources: - /topic/1/# - /longer/topic/example/ policyId2: policyDescription: access to pubsub
+ * topics 2 operations: - publish resources: - /publishOnlyTopic aws.greengrass.secretsManager: policyId3:
+ * policyDescription: access to secrets operations: - getsecret resources: - secret1
+ */
try {
if (accessControlTopic instanceof Topics) {
- accessControlMap = OBJECT_MAPPER.convertValue(((Topics)accessControlTopic).toPOJO(),
+ accessControlMap = OBJECT_MAPPER.convertValue(((Topics) accessControlTopic).toPOJO(),
new TypeReference