private static Boolean iamPermissionsAllow( final AuthContextSupplier authContext, final String[] requiredActions, final String resourceType, final String resourceId, final long resourceAllocationSize) { /* IAM checks: Is the user allowed within the account? */ // the Permissions.isAuthorized() handles the default deny for each action. boolean iamAllow = true; // Evaluate each iam action required, all must be allowed for (String action : requiredActions) { // Any deny overrides an allow // Note: explicitly set resourceOwnerAccount to null here, otherwise iam will reject even if // the ACL checks // were valid, let ACLs handle cross-account access. iamAllow &= Permissions.isAuthorized( PolicySpec.VENDOR_S3, resourceType, resourceId, null, action, authContext) && Permissions.canAllocate( PolicySpec.VENDOR_S3, resourceType, resourceId, action, authContext, resourceAllocationSize); } return iamAllow; }
public AuthContextSupplier getAuthContext() throws AuthException { return context != null ? context.getAuthContext() : Permissions.createAuthContextSupplier( Accounts.lookupPrincipalByUserId(getOwnerFullName().getUserId()), Collections.<String, String>emptyMap()); }
private static void checkAuthorized() throws ReportingException { final Context ctx = Contexts.lookup(); final User requestUser = ctx.getUser(); final AuthContextSupplier requestUserSupplier = ctx.getAuthContext(); if (!requestUser.isSystemUser() || !Permissions.isAuthorized( VENDOR_REPORTING, "", "", null, getIamActionByMessageType(), requestUserSupplier)) { throw new ReportingException( HttpResponseStatus.UNAUTHORIZED, ReportingException.NOT_AUTHORIZED, "Not authorized"); } }
private void checkActionPermission(final String actionType, final Context ctx) throws EucalyptusCloudException { if (!Permissions.isAuthorized( PolicySpec.VENDOR_CLOUDWATCH, actionType, "", ctx.getAccount(), actionType, ctx.getUser())) { throw new EucalyptusCloudException("User does not have permission"); } }
/** * Evaluates the authorization for the operation requested, evaluates IAM, ACL, and bucket policy * (bucket policy not yet supported). * * @param request * @param bucketResourceEntity * @param objectResourceEntity * @param resourceAllocationSize the size for the quota check(s) if applicable * @return */ public <T extends ObjectStorageRequestType> boolean operationAllowed( @Nonnull T request, @Nullable final S3AccessControlledEntity bucketResourceEntity, @Nullable final S3AccessControlledEntity objectResourceEntity, long resourceAllocationSize) throws IllegalArgumentException { /* * Process the operation's authz requirements based on the request type annotations */ Ats requestAuthzProperties = Ats.from(request); ObjectStorageProperties.Permission[] requiredBucketACLPermissions = null; ObjectStorageProperties.Permission[] requiredObjectACLPermissions = null; Boolean allowOwnerOnly = null; RequiresACLPermission requiredACLs = requestAuthzProperties.get(RequiresACLPermission.class); if (requiredACLs != null) { requiredBucketACLPermissions = requiredACLs.bucket(); requiredObjectACLPermissions = requiredACLs.object(); allowOwnerOnly = requiredACLs.ownerOnly(); } else { // No ACL annotation is ok, maybe a admin only op } String[] requiredActions = null; RequiresPermission perms = requestAuthzProperties.get(RequiresPermission.class); if (perms != null) { requiredActions = perms.value(); } Boolean allowAdmin = (requestAuthzProperties.get(AdminOverrideAllowed.class) != null); Boolean allowOnlyAdmin = (requestAuthzProperties.get(AdminOverrideAllowed.class) != null) && requestAuthzProperties.get(AdminOverrideAllowed.class).adminOnly(); // Must have at least one of: admin-only, owner-only, ACL, or IAM. if (requiredBucketACLPermissions == null && requiredObjectACLPermissions == null && requiredActions == null && !allowAdmin) { // Insufficient permission set on the message type. LOG.error( "Insufficient permission annotations on type: " + request.getClass().getName() + " cannot evaluate authorization"); return false; } String resourceType = null; if (requestAuthzProperties.get(ResourceType.class) != null) { resourceType = requestAuthzProperties.get(ResourceType.class).value(); } // Use these variables to isolate where all the AuthExceptions can happen on account/user // lookups User requestUser = null; String securityToken = null; Account requestAccount = null; AuthContextSupplier authContext = null; try { // Use context if available as it saves a DB lookup try { Context ctx = Contexts.lookup(request.getCorrelationId()); requestUser = ctx.getUser(); securityToken = ctx.getSecurityToken(); requestAccount = requestUser.getAccount(); authContext = ctx.getAuthContext(); } catch (NoSuchContextException e) { requestUser = null; securityToken = null; requestAccount = null; authContext = null; } // This is not an expected path, but if no context found use the request credentials itself if (requestUser == null && !Strings.isNullOrEmpty(request.getEffectiveUserId())) { requestUser = Accounts.lookupUserById(request.getEffectiveUserId()); requestAccount = requestUser.getAccount(); } if (requestUser == null) { if (!Strings.isNullOrEmpty(request.getAccessKeyID())) { if (securityToken != null) { requestUser = SecurityTokenManager.lookupUser(request.getAccessKeyID(), securityToken); } else { requestUser = Accounts.lookupUserByAccessKeyId(request.getAccessKeyID()); } requestAccount = requestUser.getAccount(); } else { // Set to anonymous user since all else failed requestUser = Principals.nobodyUser(); requestAccount = requestUser.getAccount(); } } } catch (AuthException e) { LOG.error( "Failed to get user for request, cannot verify authorization: " + e.getMessage(), e); return false; } if (allowAdmin && requestUser.isSystemAdmin()) { // Admin override return true; } if (authContext == null) { authContext = Permissions.createAuthContextSupplier( requestUser, Collections.<String, String>emptyMap()); } Account resourceOwnerAccount = null; if (resourceType == null) { LOG.error("No resource type found in request class annotations, cannot process."); return false; } else { try { // Ensure we have the proper resource entities present and get owner info if (PolicySpec.S3_RESOURCE_BUCKET.equals(resourceType)) { // Get the bucket owner. if (bucketResourceEntity == null) { LOG.error( "Could not check access for operation due to no bucket resource entity found"); return false; } else { resourceOwnerAccount = Accounts.lookupAccountByCanonicalId(bucketResourceEntity.getOwnerCanonicalId()); } } else if (PolicySpec.S3_RESOURCE_OBJECT.equals(resourceType)) { if (objectResourceEntity == null) { LOG.error( "Could not check access for operation due to no object resource entity found"); return false; } else { resourceOwnerAccount = Accounts.lookupAccountByCanonicalId(objectResourceEntity.getOwnerCanonicalId()); } } } catch (AuthException e) { LOG.error("Exception caught looking up resource owner. Disallowing operation.", e); return false; } } // Get the resourceId based on IAM resource type String resourceId = null; if (resourceId == null) { if (PolicySpec.S3_RESOURCE_BUCKET.equals(resourceType)) { resourceId = request.getBucket(); } else if (PolicySpec.S3_RESOURCE_OBJECT.equals(resourceType)) { resourceId = request.getFullResource(); } } if (allowAdmin && requestUser.isSystemUser() && iamPermissionsAllow( authContext, requiredActions, resourceType, resourceId, resourceAllocationSize)) { // Admin override return true; } if (requiredBucketACLPermissions == null && requiredObjectACLPermissions == null) { throw new IllegalArgumentException( "No requires-permission actions found in request class annotations, cannot process."); } /* ACL Checks: Is the user's account allowed? */ Boolean aclAllow = false; if (requiredBucketACLPermissions != null && requiredBucketACLPermissions.length > 0) { // Check bucket ACLs if (bucketResourceEntity == null) { // There are bucket ACL requirements but no bucket entity to check. fail. // Don't bother with other checks, this is an invalid state LOG.error("Null bucket resource, cannot evaluate bucket ACL"); return false; } // Evaluate the bucket ACL, any matching grant gives permission for (ObjectStorageProperties.Permission permission : requiredBucketACLPermissions) { aclAllow = aclAllow || bucketResourceEntity.can(permission, requestAccount.getCanonicalId()); } } // Check object ACLs, if any if (requiredObjectACLPermissions != null && requiredObjectACLPermissions.length > 0) { if (objectResourceEntity == null) { // There are object ACL requirements but no object entity to check. fail. // Don't bother with other checks, this is an invalid state LOG.error("Null bucket resource, cannot evaluate bucket ACL"); return false; } for (ObjectStorageProperties.Permission permission : requiredObjectACLPermissions) { aclAllow = aclAllow || objectResourceEntity.can(permission, requestAccount.getCanonicalId()); } } /* Resource owner only? if so, override any previous acl decisions * It is not expected that owneronly is set as well as other ACL permissions, * Regular owner permissions (READ, WRITE, READ_ACP, WRITE_ACP) are handled by the regular acl checks. * OwnerOnly should be only used for operations not covered by the other Permissions (e.g. logging, or versioning) */ aclAllow = (allowOwnerOnly ? resourceOwnerAccount.getAccountNumber().equals(requestAccount.getAccountNumber()) : aclAllow); if (aclAllow && isUserAnonymous(requestUser)) { // Skip the IAM checks for anonymous access since they will always fail and aren't valid for // anonymous users. return true; } else { Boolean iamAllow = iamPermissionsAllow( authContext, requiredActions, resourceType, resourceId, resourceAllocationSize); // Must have both acl and iam allow (account & user) return aclAllow && iamAllow; } }
@Override public boolean apply(final Allocation allocInfo) throws MetadataException { final UserFullName ownerFullName = allocInfo.getOwnerFullName(); final String instanceProfileArn = allocInfo.getRequest().getIamInstanceProfileArn(); final String instanceProfileName = allocInfo.getRequest().getIamInstanceProfileName(); if (!Strings.isNullOrEmpty(instanceProfileArn) || !Strings.isNullOrEmpty(instanceProfileName)) { final String profileAccount; final String profileName; if (!Strings.isNullOrEmpty(instanceProfileArn)) try { final Ern name = Ern.parse(instanceProfileArn); if (!(name instanceof EuareResourceName)) { throw new InvalidInstanceProfileMetadataException( "Invalid IAM instance profile ARN: " + instanceProfileArn); } profileAccount = name.getAccount(); profileName = ((EuareResourceName) name).getName(); } catch (JSONException e) { throw new InvalidInstanceProfileMetadataException( "Invalid IAM instance profile ARN: " + instanceProfileArn, e); } else { profileAccount = ownerFullName.getAccountNumber(); profileName = instanceProfileName; } final InstanceProfile profile; try { profile = Accounts.lookupInstanceProfileByName(profileAccount, profileName); } catch (AuthException e) { throw new InvalidInstanceProfileMetadataException( "Invalid IAM instance profile: " + profileAccount + "/" + profileName, e); } if (!Strings.isNullOrEmpty(instanceProfileName) && !instanceProfileName.equals(profile.getName())) { throw new InvalidInstanceProfileMetadataException( String.format( "Invalid IAM instance profile name '%s' for ARN: %s", profileName, instanceProfileArn)); } try { final AuthContextSupplier user = allocInfo.getAuthContext(); if (!Permissions.isAuthorized( PolicySpec.VENDOR_IAM, PolicySpec.IAM_RESOURCE_INSTANCE_PROFILE, Accounts.getInstanceProfileFullName(profile), AccountFullName.getInstance(profile.getAccountNumber()), PolicySpec.IAM_LISTINSTANCEPROFILES, user)) { throw new IllegalMetadataAccessException( String.format( "Not authorized to access instance profile with ARN %s for %s", profile.getInstanceProfileArn(), ownerFullName)); } final Role role = profile.getRole(); if (role != null && !Permissions.isAuthorized( PolicySpec.VENDOR_IAM, PolicySpec.IAM_RESOURCE_ROLE, Accounts.getRoleFullName(role), AccountFullName.getInstance(role.getAccountNumber()), PolicySpec.IAM_PASSROLE, user)) { throw new IllegalMetadataAccessException( String.format( "Not authorized to pass role with ARN %s for %s", role.getRoleArn(), ownerFullName)); } if (role != null) { allocInfo.setInstanceProfileArn(profile.getInstanceProfileArn()); allocInfo.setIamInstanceProfileId(profile.getInstanceProfileId()); allocInfo.setIamRoleArn(role.getRoleArn()); } else { throw new InvalidInstanceProfileMetadataException( "Role not found for IAM instance profile ARN: " + profile.getInstanceProfileArn()); } } catch (AuthException e) { throw new MetadataException("IAM instance profile error", e); } } return true; }