@Override
  public Pair<Boolean, ActionOnFailedAuthentication> authenticate(
      String username, String password, Long domainId, Map<String, Object[]> requestParameters) {
    if (s_logger.isDebugEnabled()) {
      s_logger.debug("Trying SAML2 auth for user: "******"Username or Password cannot be empty");
      return new Pair<Boolean, ActionOnFailedAuthentication>(false, null);
    }

    final UserAccount userAccount = _userAccountDao.getUserAccount(username, domainId);
    if (userAccount == null || userAccount.getSource() != User.Source.SAML2) {
      s_logger.debug(
          "Unable to find user with "
              + username
              + " in domain "
              + domainId
              + ", or user source is not SAML2");
      return new Pair<Boolean, ActionOnFailedAuthentication>(false, null);
    } else {
      User user = _userDao.getUser(userAccount.getId());
      if (user != null
          && user.getSource() == User.Source.SAML2
          && user.getExternalEntity() != null) {
        return new Pair<Boolean, ActionOnFailedAuthentication>(true, null);
      }
    }
    // Deny all by default
    return new Pair<Boolean, ActionOnFailedAuthentication>(
        false, ActionOnFailedAuthentication.INCREMENT_INCORRECT_LOGIN_ATTEMPT_COUNT);
  }
Exemple #2
0
  @Override
  public Pair<User, Account> findUserAccountByApiKey(String apiKey) {
    Transaction txn = Transaction.currentTxn();
    PreparedStatement pstmt = null;
    Pair<User, Account> userAcctPair = null;
    try {
      String sql = FIND_USER_ACCOUNT_BY_API_KEY;
      pstmt = txn.prepareAutoCloseStatement(sql);
      pstmt.setString(1, apiKey);
      ResultSet rs = pstmt.executeQuery();
      // TODO:  make sure we don't have more than 1 result?  ApiKey had better be unique
      if (rs.next()) {
        User u = new UserVO(rs.getLong(1));
        u.setUsername(rs.getString(2));
        u.setAccountId(rs.getLong(3));
        u.setSecretKey(DBEncryptionUtil.decrypt(rs.getString(4)));
        u.setState(State.valueOf(rs.getString(5)));

        AccountVO a = new AccountVO(rs.getLong(6));
        a.setAccountName(rs.getString(7));
        a.setType(rs.getShort(8));
        a.setDomainId(rs.getLong(9));
        a.setState(State.valueOf(rs.getString(10)));

        userAcctPair = new Pair<User, Account>(u, a);
      }
    } catch (Exception e) {
      s_logger.warn("Exception finding user/acct by api key: " + apiKey, e);
    }
    return userAcctPair;
  }
  @Override
  public long getEntityOwnerId() {
    User user = _entityMgr.findById(User.class, getId());
    if (user != null) {
      return user.getAccountId();
    }

    return Account
        .ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events
    // are tracked
  }
  public boolean verifyUser(Long userId) {
    User user = _accountMgr.getUserIncludingRemoved(userId);
    Account account = null;
    if (user != null) {
      account = _accountMgr.getAccount(user.getAccountId());
    }

    if ((user == null)
        || (user.getRemoved() != null)
        || !user.getState().equals(Account.State.enabled)
        || (account == null)
        || !account.getState().equals(Account.State.enabled)) {
      s_logger.warn(
          "Deleted/Disabled/Locked user with id=" + userId + " attempting to access public API");
      return false;
    }
    return true;
  }
 @Override
 public String toString() {
   return new StringBuffer("CCtxt[acct=")
       .append(account.getId())
       .append("; user="******"; id=")
       .append(contextId)
       .append("]")
       .toString();
 }
 @Override
 public void execute() throws InsufficientCapacityException, ConcurrentOperationException {
   User callerUser = _accountService.getActiveUser(UserContext.current().getCallerUserId());
   Account callerAccount = _accountService.getActiveAccountById(callerUser.getAccountId());
   Network result =
       _networkService.updateGuestNetwork(
           getId(),
           getNetworkName(),
           getDisplayText(),
           callerAccount,
           callerUser,
           getNetworkDomain(),
           getNetworkOfferingId(),
           getChangeCidr());
   if (result != null) {
     NetworkResponse response = _responseGenerator.createNetworkResponse(result);
     response.setResponseName(getCommandName());
     this.setResponseObject(response);
   } else {
     throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to update network");
   }
 }
Exemple #7
0
  @Override
  public boolean verifyRequest(Map<String, Object[]> requestParameters, Long userId)
      throws ServerApiException {
    try {
      String apiKey = null;
      String secretKey = null;
      String signature = null;
      String unsignedRequest = null;

      String[] command = (String[]) requestParameters.get("command");
      if (command == null) {
        s_logger.info("missing command, ignoring request...");
        return false;
      }

      String commandName = command[0];

      // if userId not null, that mean that user is logged in
      if (userId != null) {
        User user = ApiDBUtils.findUserById(userId);

        try {
          checkCommandAvailable(user, commandName);
        } catch (RequestLimitException ex) {
          s_logger.debug(ex.getMessage());
          throw new ServerApiException(ApiErrorCode.API_LIMIT_EXCEED, ex.getMessage());
        } catch (PermissionDeniedException ex) {
          s_logger.debug(
              "The given command:"
                  + commandName
                  + " does not exist or it is not available for user with id:"
                  + userId);
          throw new ServerApiException(
              ApiErrorCode.UNSUPPORTED_ACTION_ERROR,
              "The given command does not exist or it is not available for user");
        }
        return true;
      } else {
        // check against every available command to see if the command exists or not
        if (!_apiNameCmdClassMap.containsKey(commandName)
            && !commandName.equals("login")
            && !commandName.equals("logout")) {
          s_logger.debug(
              "The given command:"
                  + commandName
                  + " does not exist or it is not available for user with id:"
                  + userId);
          throw new ServerApiException(
              ApiErrorCode.UNSUPPORTED_ACTION_ERROR,
              "The given command does not exist or it is not available for user");
        }
      }

      // - build a request string with sorted params, make sure it's all lowercase
      // - sign the request, verify the signature is the same
      List<String> parameterNames = new ArrayList<String>();

      for (Object paramNameObj : requestParameters.keySet()) {
        parameterNames.add((String) paramNameObj); // put the name in a list that we'll sort later
      }

      Collections.sort(parameterNames);

      String signatureVersion = null;
      String expires = null;

      for (String paramName : parameterNames) {
        // parameters come as name/value pairs in the form String/String[]
        String paramValue = ((String[]) requestParameters.get(paramName))[0];

        if ("signature".equalsIgnoreCase(paramName)) {
          signature = paramValue;
        } else {
          if ("apikey".equalsIgnoreCase(paramName)) {
            apiKey = paramValue;
          } else if ("signatureversion".equalsIgnoreCase(paramName)) {
            signatureVersion = paramValue;
          } else if ("expires".equalsIgnoreCase(paramName)) {
            expires = paramValue;
          }

          if (unsignedRequest == null) {
            unsignedRequest =
                paramName + "=" + URLEncoder.encode(paramValue, "UTF-8").replaceAll("\\+", "%20");
          } else {
            unsignedRequest =
                unsignedRequest
                    + "&"
                    + paramName
                    + "="
                    + URLEncoder.encode(paramValue, "UTF-8").replaceAll("\\+", "%20");
          }
        }
      }

      // if api/secret key are passed to the parameters
      if ((signature == null) || (apiKey == null)) {
        s_logger.debug(
            "Expired session, missing signature, or missing apiKey -- ignoring request. Signature: "
                + signature
                + ", apiKey: "
                + apiKey);
        return false; // no signature, bad request
      }

      Date expiresTS = null;
      // FIXME: Hard coded signature, why not have an enum
      if ("3".equals(signatureVersion)) {
        // New signature authentication. Check for expire parameter and its validity
        if (expires == null) {
          s_logger.debug(
              "Missing Expires parameter -- ignoring request. Signature: "
                  + signature
                  + ", apiKey: "
                  + apiKey);
          return false;
        }
        synchronized (_dateFormat) {
          try {
            expiresTS = _dateFormat.parse(expires);
          } catch (ParseException pe) {
            s_logger.debug("Incorrect date format for Expires parameter", pe);
            return false;
          }
        }
        Date now = new Date(System.currentTimeMillis());
        if (expiresTS.before(now)) {
          s_logger.debug(
              "Request expired -- ignoring ...sig: " + signature + ", apiKey: " + apiKey);
          return false;
        }
      }

      TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.CLOUD_DB);
      txn.close();
      User user = null;
      // verify there is a user with this api key
      Pair<User, Account> userAcctPair = _accountMgr.findUserByApiKey(apiKey);
      if (userAcctPair == null) {
        s_logger.debug(
            "apiKey does not map to a valid user -- ignoring request, apiKey: " + apiKey);
        return false;
      }

      user = userAcctPair.first();
      Account account = userAcctPair.second();

      if (user.getState() != Account.State.enabled
          || !account.getState().equals(Account.State.enabled)) {
        s_logger.info(
            "disabled or locked user accessing the api, userid = "
                + user.getId()
                + "; name = "
                + user.getUsername()
                + "; state: "
                + user.getState()
                + "; accountState: "
                + account.getState());
        return false;
      }

      try {
        checkCommandAvailable(user, commandName);
      } catch (PermissionDeniedException ex) {
        s_logger.debug(
            "The given command:" + commandName + " does not exist or it is not available for user");
        throw new ServerApiException(
            ApiErrorCode.UNSUPPORTED_ACTION_ERROR,
            "The given command:"
                + commandName
                + " does not exist or it is not available for user with id:"
                + userId);
      }

      // verify secret key exists
      secretKey = user.getSecretKey();
      if (secretKey == null) {
        s_logger.info(
            "User does not have a secret key associated with the account -- ignoring request, username: "******"HmacSHA1");
      SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes(), "HmacSHA1");
      mac.init(keySpec);
      mac.update(unsignedRequest.getBytes());
      byte[] encryptedBytes = mac.doFinal();
      String computedSignature = Base64.encodeBase64String(encryptedBytes);
      boolean equalSig = signature.equals(computedSignature);
      if (!equalSig) {
        s_logger.info(
            "User signature: "
                + signature
                + " is not equaled to computed signature: "
                + computedSignature);
      } else {
        CallContext.register(user, account);
      }
      return equalSig;
    } catch (ServerApiException ex) {
      throw ex;
    } catch (Exception ex) {
      s_logger.error("unable to verify request signature");
    }
    return false;
  }
  // NOTE: handle() only handles over the wire (OTW) requests from integration.api.port 8096
  // If integration api port is not configured, actual OTW requests will be received by ApiServlet
  @SuppressWarnings({"unchecked", "rawtypes"})
  @Override
  public void handle(HttpRequest request, HttpResponse response, HttpContext context)
      throws HttpException, IOException {

    // Create StringBuffer to log information in access log
    StringBuffer sb = new StringBuffer();
    HttpServerConnection connObj = (HttpServerConnection) context.getAttribute("http.connection");
    if (connObj instanceof SocketHttpServerConnection) {
      InetAddress remoteAddr = ((SocketHttpServerConnection) connObj).getRemoteAddress();
      sb.append(remoteAddr.toString() + " -- ");
    }
    sb.append(StringUtils.cleanString(request.getRequestLine().toString()));

    try {
      List<NameValuePair> paramList = null;
      try {
        paramList = URLEncodedUtils.parse(new URI(request.getRequestLine().getUri()), "UTF-8");
      } catch (URISyntaxException e) {
        s_logger.error("Error parsing url request", e);
      }

      // Use Multimap as the parameter map should be in the form (name=String, value=String[])
      // So parameter values are stored in a list for the same name key
      // APITODO: Use Guava's (import com.google.common.collect.Multimap;)
      // (Immutable)Multimap<String, String> paramMultiMap = HashMultimap.create();
      // Map<String, Collection<String>> parameterMap = paramMultiMap.asMap();
      Map parameterMap = new HashMap<String, String[]>();
      String responseType = BaseCmd.RESPONSE_TYPE_XML;
      for (NameValuePair param : paramList) {
        if (param.getName().equalsIgnoreCase("response")) {
          responseType = param.getValue();
          continue;
        }
        parameterMap.put(param.getName(), new String[] {param.getValue()});
      }

      // Check responseType, if not among valid types, fallback to JSON
      if (!(responseType.equals(BaseCmd.RESPONSE_TYPE_JSON)
          || responseType.equals(BaseCmd.RESPONSE_TYPE_XML)))
        responseType = BaseCmd.RESPONSE_TYPE_XML;

      try {
        // always trust commands from API port, user context will always be
        // UID_SYSTEM/ACCOUNT_ID_SYSTEM
        UserContext.registerContext(_systemUser.getId(), _systemAccount, null, true);
        sb.insert(
            0,
            "(userId="
                + User.UID_SYSTEM
                + " accountId="
                + Account.ACCOUNT_ID_SYSTEM
                + " sessionId="
                + null
                + ") ");
        String responseText = handleRequest(parameterMap, true, responseType, sb);
        sb.append(" 200 " + ((responseText == null) ? 0 : responseText.length()));

        writeResponse(response, responseText, HttpStatus.SC_OK, responseType, null);
      } catch (ServerApiException se) {
        String responseText = getSerializedApiError(se, parameterMap, responseType);
        writeResponse(
            response,
            responseText,
            se.getErrorCode().getHttpCode(),
            responseType,
            se.getDescription());
        sb.append(" " + se.getErrorCode() + " " + se.getDescription());
      } catch (RuntimeException e) {
        // log runtime exception like NullPointerException to help identify the source easier
        s_logger.error("Unhandled exception, ", e);
        throw e;
      }
    } finally {
      s_accessLogger.info(sb.toString());
      UserContext.unregisterContext();
    }
  }
 public long getCallingUserId() {
   return user.getId();
 }
 public String getCallingUserUuid() {
   return user.getUuid();
 }