چرا یک Apps Script نمیتواند از طریق VPN به برنامه داخلی شما برسد
Apps Script روی شبکه گوگل اجرا میشود، نه روی لپتاپی که VPN دارد. مسیر داده را برای ماشینی طراحی کنید که درخواست را میفرستد.
داشبورد در مرورگر لپتاپ بیمشکل باز میشود، اما همان اسکریپت صفحهگسترده با خطای در دسترس نبودن نشانی شکست میخورد. روشن یا خاموش کردن VPN چیزی را عوض نمیکند، چون درخواست اصلاً از لپتاپ خارج نمیشود. Apps Script روی زیرساخت گوگل اجرا میشود و اتصال خودش را از آنجا باز میکند. همین یک واقعیت کل طراحی را تعیین میکند.
پیش از هر تغییری دو پرسش را جدا کنید: کدام ماشین درخواست را میفرستد، و گیرنده کدام مدرک را میپذیرد.
درخواست هرگز روی لپتاپ شما آغاز نمیشود
یک زبانه مرورگر از لپتاپ، از طریق آداپتور VPN، پسوند DNS داخلی و به زیرشبکه خصوصی میفرستد. UrlFetchApp از میزبان تحت مدیریت گوگل میفرستد، بنابراین حلکنندههای گوگل، نشانیهای خروج گوگل و هیچیک از مسیرهای split-tunnel شما را نمیبیند. دو مسیر یک سند صفحهگسترده را شریکاند، نه یک موقعیت شبکه. در گزارش دسترسی برنامه، تلاش اسکریپت بهصورت نشانی گوگل دیده میشود نه نشانی از استخر VPN، و این سریعترین تأییدی است که خواهید گرفت.
به همین دلیل اصلاحهای محلی هیچ کاری نمیکنند. نشانهرفتن لپتاپ به حلکننده دیگری، راهاندازی دوباره مشتری VPN یا افزودن یک ورودی در hosts مسیر مرورگر را عوض میکند و مسیر اسکریپت را دقیقاً همانطور که بود میگذارد.
این چه چیزی را کنار میگذارد
نقطه پایانی فقط داخلی از Apps Script در دسترس نیست، و فهرست مجاز IP در این موقعیت جایگزین ضعیفی برای کنترل دسترسی است. محدودههای خروج گوگل گستردهاند، با مشتریان دیگر شریکاند و بستن آنها به یک اسکریپت ممکن نیست. مرجع UrlFetchApp میگوید درخواستها از استخر IP گوگل میآیند، که نسخه معتبر همان ادعاست. باز کردن برنامه داخلی به این محدودهها ترافیکی را میپذیرد که نمیتوانید به کسی نسبت دهید.
نشستهای مرورگر هم همینگونه رفتار میکنند. یک کوکی یا نشست SSO در مرورگر لپتاپ با درخواست همراه نمیشود، چون درخواست یک مشتری تازه HTTPS بدون حالت نشست است. هر چیزی که به تغییرمسیر SSO مرورگر وابسته باشد، در همان تغییرمسیر تمام میشود نه در دادههای شما.
دو شکل عملی
شکل اول به اسکریپت یک API تأییدشده میدهد. سرویس داخلی را پشت دروازهای منتشر کنید که فراخوان را احراز هویت میکند، سپس اسکریپت مدرکی را ارائه دهد که دروازه میپذیرد، مانند توکن حساب سرویس. در Apps Script این یعنی یک کتابخانه OAuth2 یا ScriptApp.getOAuthToken()، بههمراه فهرست مجاز هویت فراخوان در سمت API بهجای فهرست مجاز IP.
شکل دوم جهت را برمیگرداند. یک کار داخلی از سیستم خصوصی پرسوجو میکند و نتیجهای کنترلشده را در یک Sheet، یک شیء Cloud Storage یا جدول BigQuery که اسکریپت میخواند منتشر میکند. یک کار Cloud Run، یک زمانبند محلی یا یک گام ETL موجود میتوانند همان کار باشند و هیچیک لازم نیست اتصال ورودی بپذیرد. سپس صفحهگسترده بهجای یک رابط، یک مجموعه داده مصرف میکند.
کدام شکل برنده میشود به تازگی، کنترل در سطح فیلد و اینکه چه کسی باید بتواند خواننده را ممیزی کند بستگی دارد.
نتیجه منتشرشده چه چیزی باید داشته باشد
جریان در جهت معکوس به یک قرارداد صریح نیاز دارد: فیلدهایی که حمل میکند، بازه تازهسازی، گروه خواننده، و اینکه وقتی کار داخلی شکست میخورد چه میشود. بدون این چهار، صفحهگسترده بیصدا اعداد دیروز را نشان میدهد. یک ستون زمانمهر تولیدشده و شمارش سطر اضافه کنید تا انتشار کهنه یا ناقص در خود صفحه دیده شود، بدون اینکه کسی گزارشی باز کند.
جهت API هم به قرارداد نیاز دارد: دروازه کدام مدرک را میپذیرد، توکن چه scopeهایی حمل میکند و کدام هویتهای فراخوان مجازند. پاسخ 200 که صفحه ورود دارد فراخوانی موفق نیست، پس بدنه را بررسی کنید نه فقط کد وضعیت.
خطا را از سمت درست بخوانید
Apps Script میزبان در دسترس نبودن را بهصورت استثنای در دسترس نبودن نشانی گزارش میکند، که پیام اتصال ردشده مرورگر نیست. 403 از دروازه یعنی درخواست رسیده و مدرک یا سیاستی رد شده است. صفحه ورود HTML یعنی درخواست به لایه تعاملی رسیده که اسکریپت نمیتواند کامل کند. سه شکست متفاوت با سه مالک متفاوت.
گزارش اسکریپت را کنار نتیجه مرورگر نگه دارید نه اینکه یکی را با دیگری جایگزین کنید. پرسش باقیمانده آنگاه یک تصمیم یکپارچهسازی معمولی است: به آن محیط دسترسی لازم را بدهید، یا نتیجهای کنترلشده به آن تحویل دهید.