mongoDB白名单IP

mongoDB whitelist IP

我看到了类似的帖子,但是 none 正在帮助我解决问题。

按照从头开始构建 MERN 应用程序的 Udemy 教程,我卡在了 mongoose 连接上。

这是我的 index.js 代码:

const express = require("express");
const mongoose = require("mongoose");

const app = express();

app.use(express.json());

app.listen(5000, () => console.log("Server started on port 5000"));

app.use("/snippet", require("./routers/snippetRouter"));

mongoose.connect("mongodb+srv://snippetUser:_password_@
  snippet-manager.sometext.mongodb.net/main?retryWrites=
  true&w=majority", {
    useNewUrlParser: true,
    useUnifiedTopology: true
}, (err) => {
  if (err) return console.log("error here " + err);
  console.log("Connected to MongoDB");
});

这是我收到的错误:

Server started on port 5000
error here MongooseServerSelectionError: Could not connect to any 
servers in your MongoDB Atlas cluster. One common reason is 
that you're trying to access the database from an IP that isn't 
whitelisted. Make sure your current IP address is on your Atlas 
cluster's IP whitelist:
https://docs.atlas.mongodb.com/security-whitelist/ 

如上所述,我看到与未列入白名单的 IP 相关的类似错误。

但是,在我的 mongoDB 帐户中,我的 IP 似乎已经列入白名单:

在上面的截图中,空白部分是我的IP所在的位置(就在它说“包括您当前的IP地址”之前)。

既然我的 IP 列在那里,那是否意味着我的 IP 已列入白名单?

如果没有,我该如何将我的 IP 列入白名单?

经过几天的挫折,我进入 Mongo Atlas,然后进入网络访问并将设置更改为“允许从任何地方访问”。它删除了我的 IP 地址并将其更改为通用 IP 地址。

这与我在 Udemy 上遵循的教程有所不同,但它确实奏效了,我终于可以继续学习剩余的课程了。

这是我在其他地方留下的答案。希望它能帮助遇到这个问题的人:

此脚本将在 my gist

保持最新

为什么

mongo atlas 以合理的价格提供对托管 mongo 数据库的访问。托管容器的 CSP 对其托管的 mongo 数据库收费过高。他们都建议设置一个不安全的 CIDR (0.0.0.0/0) 以允许容器访问集群。这显然是荒谬的。

此入口点脚本可用于维护最低权限访问。只有服务的当前托管 IP 地址被列入白名单。

用法

  • 设置为 Dockerfile
  • 的入口点
  • 运行 在 cloud init / VM 启动中,如果不使用容器(并删除最后一行 exec "$@",因为它仅用于容器

行为

uses the mongo atlas project IP access list endpoints

  • 将检测容器的托管 IP 地址,并使用 mongo atlas API
  • 将其与集群列入白名单
  • 如果服务没有创建白名单条目
  • 如果该服务具有与当前 IP 匹配的现有白名单条目,则无变化
  • 如果服务 IP 已更改,则删除旧条目并创建新条目

when a whitelist entry is created the service sleeps for 60s to wait for atlas to propagate access to the cluster

环境

setup

  1. create API key for org
  2. add API key to project
  3. 复制 public 密钥 (MONGO_ATLAS_API_PK) 和密钥 (MONGO_ATLAS_API_SK)
  4. 转到项目设置页面并复制项目 ID (MONGO_ATLAS_API_PROJECT_ID)

provide the following values in the env of the container service

  • SERVICE_NAME: 用于创建/更新(删除旧的)白名单条目的唯一名称
  • MONGO_ATLAS_API_PK:第 3 步
  • MONGO_ATLAS_API_SK:第 3 步
  • MONGO_ATLAS_API_PROJECT_ID:第 4 步

部门

# alpine / apk
apk update \
  && apk add --no-cache \
     bash \
     curl \
     jq
     
# ubuntu / apt
export DEBIAN_FRONTEND=noninteractive \
  && apt-get update  \
  && apt-get -y install \
     bash \
     curl \
     jq

脚本

#!/usr/bin/env bash

# -- ENV -- #
# these must be available to the container service at runtime
#
# SERVICE_NAME
#
# MONGO_ATLAS_API_PK
# MONGO_ATLAS_API_SK
# MONGO_ATLAS_API_PROJECT_ID
#
# -- ENV -- #

set -e

mongo_api_base_url='https://cloud.mongodb.com/api/atlas/v1.0'

check_for_deps() {
  deps=(
    bash
    curl
    jq
  )

 for dep in "${deps[@]}"; do
   if [ ! "$(command -v $dep)" ]
   then
    echo "dependency [$dep] not found. exiting"
    exit 1
   fi
 done
}

make_mongo_api_request() {
  local request_method=""
  local request_url=""
  local data=""

  curl -s \
    --user "$MONGO_ATLAS_API_PK:$MONGO_ATLAS_API_SK" --digest \
    --header "Accept: application/json" \
    --header "Content-Type: application/json" \
    --request "$request_method" "$request_url" \
    --data "$data"
}

get_access_list_endpoint() {
  echo -n "$mongo_api_base_url/groups/$MONGO_ATLAS_API_PROJECT_ID/accessList"
}

get_service_ip() {
  echo -n "$(curl https://ipinfo.io/ip -s)"
}

get_previous_service_ip() {
  local access_list_endpoint=`get_access_list_endpoint`

  local previous_ip=`make_mongo_api_request 'GET' "$access_list_endpoint" \
                    | jq --arg SERVICE_NAME "$SERVICE_NAME" -r \
                    '.results[]? as $results | $results.comment | if test("\[\($SERVICE_NAME)\]") then $results.ipAddress else empty end'`

  echo "$previous_ip"
}

whitelist_service_ip() {
  local current_service_ip=""
  local comment="Hosted IP of [$SERVICE_NAME] [set@$(date +%s)]"

  if (( "${#comment}" > 80 )); then
    echo "comment field value will be above 80 char limit: \"$comment\""
    echo "comment would be too long due to length of service name [$SERVICE_NAME] [${#SERVICE_NAME}]"
    echo "change comment format or service name then retry. exiting to avoid mongo API failure"
    exit 1
  fi
  
  echo "whitelisting service IP [$current_service_ip] with comment value: \"$comment\""

  response=`make_mongo_api_request \
            'POST' \
            "$(get_access_list_endpoint)?pretty=true" \
            "[
              {
                \"comment\" : \"$comment\",
                \"ipAddress\": \"$current_service_ip\"
              }
            ]" \
            | jq -r 'if .error then . else empty end'`

  if [[ -n "$response" ]];
  then
    echo 'API error whitelisting service'
    echo "$response"
    exit 1
  else
    echo "whitelist request successful"
    echo "waiting 60s for whitelist to propagate to cluster"
    sleep 60s
  fi 
}

delete_previous_service_ip() {
  local previous_service_ip=""

  echo "deleting previous service IP address of [$SERVICE_NAME]"

  make_mongo_api_request \
    'DELETE' \
    "$(get_access_list_endpoint)/$previous_service_ip"
}

set_mongo_whitelist_for_service_ip() {
  local current_service_ip=`get_service_ip`
  local previous_service_ip=`get_previous_service_ip`

  if [[ -z "$previous_service_ip" ]]; then
    echo "service [$SERVICE_NAME] has not yet been whitelisted"

    whitelist_service_ip "$current_service_ip"
  elif [[ "$current_service_ip" == "$previous_service_ip" ]]; then
    echo "service [$SERVICE_NAME] IP has not changed"
  else  
    echo "service [$SERVICE_NAME] IP has changed from [$previous_service_ip] to [$current_service_ip]"

    delete_previous_service_ip "$previous_service_ip"
    whitelist_service_ip "$current_service_ip"
  fi
}

check_for_deps
set_mongo_whitelist_for_service_ip

# run CMD
exec "$@"