<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:media="http://search.yahoo.com/mrss/">
  <channel>
    <title>Full · 仁才徳</title>
    <link>https://jared.lynskey.co.nz/ja/tags/full/</link>
    <description>ソフトウェアエンジニアリングと開発組織のリーダーシップについて。評価、採用とチームの拡大、CI/CD、DevOps モニタリング、エージェンティック AI。ソウルより。</description>
    <generator>Hugo</generator>
    <language>ja</language>
    <copyright>© 2026 仁才徳</copyright>
    <lastBuildDate>Wed, 28 Oct 2026 00:00:00 +1300</lastBuildDate>
    <atom:link href="https://jared.lynskey.co.nz/ja/tags/full/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>SSHログインをSlackに通知する：PAMとWebhookを使った設定方法</title>
      <link>https://jared.lynskey.co.nz/ja/posts/2021/2021-12-14-ssh-log/</link>
      <guid isPermaLink="true">https://jared.lynskey.co.nz/ja/posts/2021/2021-12-14-ssh-log/</guid>
      <pubDate>Tue, 14 Dec 2021 11:30:03 +0000</pubDate>
      <dc:creator>Jared Lynskey</dc:creator>
      <category>dev</category>
      <category>full</category>
      <category>stack</category>
      <category>useful</category>
      <category>slack</category>
      <category>ssh</category>
      <category>proactive</category>
      <category>ops</category>
      <description>SSHのログイン通知をSlackで受け取る方法です。PAMとSlackのIncoming Webhookを使い、誰かがサーバーにSSHでログインしようとしたら通知が届くようにします。ログイン成功時の通知もオプションで付けられます。</description>
      <content:encoded><![CDATA[
<h2 class="relative group">目的
    <div id="目的" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e7%9b%ae%e7%9a%84" aria-label="アンカー">#</a>
    </span>
    
</h2>
<ul>
<li>SSHでは、ログイン試行があったタイミングで任意のコマンドを実行できます。この記事では、Slackと連携させつつPAMの実行順序を制御する方法を紹介します。</li>
</ul>

<h2 class="relative group">Slack APIのWebhook
    <div id="slack-apiのwebhook" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#slack-api%e3%81%aewebhook" aria-label="アンカー">#</a>
    </span>
    
</h2>
<ul>
<li>
<p>アプリの作り方は<a href="https://api.slack.com/messaging/webhooks"  target="_blank" rel="noreferrer">こちら</a>にまとまっています。</p>
</li>
<li>
<p>Slackアプリを作成してWebhookを有効にし、SSHからの通知を受け取るためのIncoming Webhookを用意してください。</p>
</li>
</ul>

<h2 class="relative group">ログイン失敗時の通知スクリプト
    <div id="ログイン失敗時の通知スクリプト" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e3%83%ad%e3%82%b0%e3%82%a4%e3%83%b3%e5%a4%b1%e6%95%97%e6%99%82%e3%81%ae%e9%80%9a%e7%9f%a5%e3%82%b9%e3%82%af%e3%83%aa%e3%83%97%e3%83%88" aria-label="アンカー">#</a>
    </span>
    
</h2>
<ul>
<li>スクリプトはどこに置いても構いません。私は <code>/var/opt/notify-attempt.sh</code> に置きました。</li>
</ul>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">#!/bin/bash
</span></span><span class="line"><span class="cl">if [ &#34;$PAM_TYPE&#34; != &#34;close_session&#34; ]; then
</span></span><span class="line"><span class="cl">        url=&#34;&lt;YOUR SLACK WEBHOOK&gt;&#34;
</span></span><span class="line"><span class="cl">        channel=&#34;#channel&#34;
</span></span><span class="line"><span class="cl">        host=&#34;$(hostname)&#34;
</span></span><span class="line"><span class="cl">        content=&#34;\&#34;attachments\&#34;: [ { \&#34;mrkdwn_in\&#34;: [\&#34;text\&#34;, \&#34;fallback\&#34;], \&#34;fallback\&#34;: \&#34;SSH login: $PAM_USER connected to \`$host\`\&#34;, \&#34;text\&#34;: \&#34;SSH login to \`$host\`\&#34;, \&#34;fields\&#34;: [ { \&#34;title\&#34;: \&#34;User\&#34;, \&#34;value\&#34;: \&#34;$PAM_USER\&#34;, \&#34;short\&#34;: true }, { \&#34;title\&#34;: \&#34;IP Address\&#34;, \&#34;value\&#34;: \&#34;$PAM_RHOST\&#34;, \&#34;short\&#34;: true } ], \&#34;color\&#34;: \&#34;#F35A00\&#34; } ]&#34;
</span></span><span class="line"><span class="cl">        curl -X POST --data-urlencode &#34;payload={\&#34;channel\&#34;: \&#34;$channel\&#34;, \&#34;mrkdwn\&#34;: true, \&#34;username\&#34;: \&#34;SSH Notifications\&#34;, $content, \&#34;icon_emoji\&#34;: \&#34;:inbox-tray:\&#34;}&#34; &#34;$url&#34; &amp;
</span></span><span class="line"><span class="cl">fi
</span></span><span class="line"><span class="cl">exit</span></span></code></pre></div></div>

<h3 class="relative group">他のSSHイベントについて
    <div id="他のsshイベントについて" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e4%bb%96%e3%81%aessh%e3%82%a4%e3%83%99%e3%83%b3%e3%83%88%e3%81%ab%e3%81%a4%e3%81%84%e3%81%a6" aria-label="アンカー">#</a>
    </span>
    
</h3>
<ul>
<li>ログイン成功など、他のイベントも通知したい場合はファイルを2つ作るのがおすすめです。</li>
<li>それぞれのファイルに、Slackへ送るJSONを書いておきます。</li>
<li><code>fallback\&quot;: \&quot;SSH login: $PAM_USER connected to \</code>$host`&quot;` の行はイベントに合わせて書き換えてください。</li>
<li>OpenSSHがこれらのスクリプトをどう使うかは、下の設定を見れば分かります。</li>
</ul>

<h3 class="relative group">sshの設定
    <div id="sshの設定" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#ssh%e3%81%ae%e8%a8%ad%e5%ae%9a" aria-label="アンカー">#</a>
    </span>
    
</h3>
<p>ログイン成功時の通知はコメントアウトしてあります。使いたい場合はコメントを外せば、成功時にもSlackへ通知が飛びます。
該当行：<code># auth  optional            pam_exec.so /var/opt/notify-login.sh</code></p>
<p>[success=2] は「ログインに成功したら2行スキップする」という意味で、これで失敗時の通知を飛ばしています。</p>
<p>ファイル：<code>/etc/pam.d/common-auth</code></p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl"># /etc/pam.d/common-auth - authentication settings common to all services
</span></span><span class="line"><span class="cl">#
</span></span><span class="line"><span class="cl"># This file is included from other service-specific PAM config files,
</span></span><span class="line"><span class="cl"># and should contain a list of the authentication modules that define
</span></span><span class="line"><span class="cl"># the central authentication scheme for use on the system
</span></span><span class="line"><span class="cl"># (e.g., /etc/shadow, LDAP, Kerberos, etc.). The default is to use the
</span></span><span class="line"><span class="cl"># traditional Unix authentication mechanisms.
</span></span><span class="line"><span class="cl">#
</span></span><span class="line"><span class="cl"># As of pam 1.0.1-6, this file is managed by pam-auth-update by default.
</span></span><span class="line"><span class="cl"># To take advantage of this, it is recommended that you configure any
</span></span><span class="line"><span class="cl"># local modules either before or after the default block, and use
</span></span><span class="line"><span class="cl"># pam-auth-update to manage selection of other modules. See
</span></span><span class="line"><span class="cl"># pam-auth-update(8) for details.
</span></span><span class="line"><span class="cl"># here are the per-package modules (the &#34;Primary&#34; block)
</span></span><span class="line"><span class="cl">auth  [success=2 default=ignore]   pam_unix.so nullok
</span></span><span class="line"><span class="cl">auth  optional            pam_exec.so /var/opt/notify-attempt.sh
</span></span><span class="line"><span class="cl"># here&#39;s the fallback if no module succeeds
</span></span><span class="line"><span class="cl">auth  requisite            pam_deny.so
</span></span><span class="line"><span class="cl"># prime the stack with a positive return value if there isn&#39;t one already;
</span></span><span class="line"><span class="cl"># this avoids us returning an error just because nothing sets a success code
</span></span><span class="line"><span class="cl"># since the modules above will each just jump around
</span></span><span class="line"><span class="cl"># For successful login, uncomment the below line, ensure the file exists.
</span></span><span class="line"><span class="cl"># auth  optional            pam_exec.so /var/opt/notify-login.sh
</span></span><span class="line"><span class="cl"># auth  required            pam_permit.so
</span></span><span class="line"><span class="cl"># and here are more per-package modules (the &#34;Additional&#34; block)
</span></span><span class="line"><span class="cl">auth  optional            pam_cap.so
</span></span><span class="line"><span class="cl"># end of pam-auth-update config</span></span></code></pre></div></div>

<h2 class="relative group">ありがとうございました！
    <div id="ありがとうございました" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e3%81%82%e3%82%8a%e3%81%8c%e3%81%a8%e3%81%86%e3%81%94%e3%81%96%e3%81%84%e3%81%be%e3%81%97%e3%81%9f" aria-label="アンカー">#</a>
    </span>
    
</h2>
<ul>
<li>質問やコメントがあれば、気軽に直接連絡してください</li>
</ul>
]]></content:encoded>
      <media:content url="https://jared.lynskey.co.nz/en/posts/2021/2021-12-14-ssh-log/featured.jpeg" medium="image" type="image/jpeg" />
    </item>
  </channel>
</rss>
