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;
 }
예제 #2
0
 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");
    }
  }
예제 #4
0
 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;
    }
  }
예제 #6
0
    @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;
    }