Ubuntu(Lightsailおよびmultipass仮想環境)のMySQLにローカルからSSH経由で接続

Ubuntu(Lightsailおよびmultipass仮想) に Blazor WebAssemblyおよびASP.NET API アプリを構築してデプロイ

 

デプロイするアプリはMySQLと同じサーバーに置くつもりなので問題ないのだけれど、ローカルPCで動かすにあたっては、multipass上の仮想サーバーやLightsailの中のMySQLにアクセスさせたい。

とはいえ、MySQL用のポートやらを公開はしたくない。ので、プログラムからもローカル開発時はSSH経由でMySQLに接続させる。

https://mysqlconnector.net/tutorials/connect-ssh/

を参考に、SSH経由でMySQLで接続するサンプル。

SSH.NET の参照設定を行う。

using Renci.SshNet;

namespace SetlistShare.Dao;

/// <summary>
/// 
/// </summary>
public class ConnectionHelper
{

    ///<summary>SSH接続</summary>
    /// <param name="host">ホスト名</param>
    /// <param name="username">ユーザー名</param>
    /// <param name="password">パスワード</param>
    /// <param name="keyFile">秘密鍵ファイル</param>
    /// <param name="passPhrase">秘密鍵のパスフレーズ</param>
    /// <param name="port">ポート番号</param>
    public static (SshClient sshClient, int Port) ConnectSsh(
        string host, 
        string username, 
        string? password = null,
        string? keyFile = null,
        string? passPhrase = null,
        int port = 22)
    {
        if (string.IsNullOrEmpty(password) && string.IsNullOrEmpty(keyFile))
        {
            throw new ArgumentException("Either password or keyFile must be specified.");
        }

        var authMethods = new List<AuthenticationMethod>();
        if (!string.IsNullOrEmpty(keyFile))
        {   
            var key = new PrivateKeyFile(keyFile, passPhrase);
            authMethods.Add(new PrivateKeyAuthenticationMethod(username, key));
        }
        if (!string.IsNullOrEmpty(password))
        {
            authMethods.Add(new PasswordAuthenticationMethod(username, password));
        }

        var connectionInfo = new ConnectionInfo(host, port, username, authMethods.ToArray());
        var sshClient = new SshClient(connectionInfo);

        sshClient.Connect();

        return (sshClient, port);
    }

    ///<summary>SSH接続</summary>
    /// <param name="host">ホスト名</param>
    /// <param name="username">ユーザー名</param>
    /// <param name="password">パスワード</param>
    /// <param name="keyFile">秘密鍵ファイル</param>
    /// <param name="passPhrase">秘密鍵のパスフレーズ</param>
    /// <param name="port">ポート番号</param>
    /// <param name="dbHost">データベースホスト名</param>
    /// <param name="dbPort">データベースポート番号</param>
    public static (SshClient sshClient, int Port) ConnectDatabaseViaSsh(
        string host, 
        string username, 
        string? password = null,
        string? keyFile = null,
        string? passPhrase = null,
        int port = 22,
        string? dbHost = "localhost",
        int dbPort = 3306)
    {

        var (sshClient, sshPort) = ConnectSsh(host, username, password, keyFile, passPhrase, port);

        var forwardPort = new ForwardedPortLocal("127.0.0.1", dbHost, (uint)dbPort);
        sshClient.AddForwardedPort(forwardPort);
        forwardPort.Start();

        return (sshClient, (int) forwardPort.BoundPort);
    }
}

接続の確認

using MySql.Data.MySqlClient;
using SetlistShare.Dao;
namespace SetlistShare.Test;

public class ConnectionHelperTest
{
    [Fact]
    public void ConnectSshTest()
    {
        var (sshclient, port) =  ConnectionHelper.ConnectDatabaseViaSsh (
            "lightsail.local", 
            "SSHユーザーID", 
            "SSHぱすわーど");
        using (sshclient)
        {

            var builder = new MySqlConnectionStringBuilder 
            {
                Server = "127.0.0.1",
                Port = (uint)port,
                UserID = "DBユーザーID",
                Password = "DBパスワード"
            };

            using (var conn = new MySqlConnection(builder.ConnectionString))
            {
                conn.Open();
                using (var cmd = new MySqlCommand("SELECT * FROM setlistshare.Person", conn))
                {
                    using (var reader = cmd.ExecuteReader())
                    {
                        var users = new List<dynamic>();
                        while (reader.Read())
                        {
                            users.Add(
                                new {
                                    Id = reader.GetInt32(0),
                                    Name = reader.GetString(1),
                                    Email = reader.GetString(2)}
                            );
                        }
                        users.ForEach(user => Console.WriteLine($"{user}"));
                    }
                }
            }
        }
    }
}

無事データ取得できました。

Follow me!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です