【Go】 발판 서버 경유 (ssh) 로 VPC 엔드포인트의 Elasticsearch Service 에 로컬로부터 접속한다 【AWS】
14424 단어 5SSHElasticsearchAWS
하고 싶은 일
발판 서버를 통해 (ssh) 프라이빗 서브넷의 RDS(MySQL)에 연결하는 것과 마찬가지로 VPC 엔드포인트의 Elasticsearch Service에도 발판 서버를 통해 연결하는 것이 목표입니다.
ssh 및 curl 명령을 사용하면 다음과 같이 쉽게 로컬에서 연결할 수 있지만 이번에는 Go 프로그램으로 연결하는 것을 목표로 합니다.
ssh -i <path/to/private-key> <username>@<hostname> curl -s '<ES_ENDPOINT>/_cat/indices?format=json&pretty'
전제
다음과 같은 아키텍처를 가정합니다. 보안 그룹은 좋은 느낌으로 설정되어 있다고 가정합니다.
구현
Elasticsearch의 클라이언트 라이브러리는 Elastic의 공식 elastic/go-elasticsearch을 사용합니다.
구현의 포인트는 http.RoundTripper (http.Transport)
의 Dial에 SSH Client의 Dial을 이용하는 것입니다.
package main
import (
"context"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"log"
"net"
"net/http"
"os"
"time"
"github.com/elastic/go-elasticsearch/v8"
"github.com/elastic/go-elasticsearch/v8/esapi"
"golang.org/x/crypto/ssh"
)
func main() {
log.SetFlags(log.LstdFlags | log.Lshortfile)
var (
sshUser = os.Getenv("SSH_USER")
sshHost = os.Getenv("SSH_HOST")
sshPort = os.Getenv("SSH_PORT")
sshPrivateKey = os.Getenv("SSH_PRIVATE_KEY")
esEndpoint = os.Getenv("ES_ENDPOINT")
)
// ------------------------------
// 秘密鍵ファイルの読み込み
// ------------------------------
b, err := ioutil.ReadFile(sshPrivateKey)
if err != nil {
log.Fatal(err)
}
signer, err := ssh.ParsePrivateKey(b)
if err != nil {
log.Fatal(err)
}
// ------------------------------
// SSH クライアントの生成
// ------------------------------
sshConf := ssh.ClientConfig{
User: sshUser,
Auth: []ssh.AuthMethod{
ssh.PublicKeys(signer),
},
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
return nil
},
Timeout: 10 * time.Second,
}
sshClient, err := ssh.Dial("tcp", net.JoinHostPort(sshHost, sshPort), &sshConf)
if err != nil {
log.Fatal(err)
}
defer sshClient.Close()
// ------------------------------
// Elasticsearch クライアントの生成
// ------------------------------
esConf := elasticsearch.Config{
Addresses: []string{esEndpoint},
Transport: &http.Transport{
Proxy: http.ProxyFromEnvironment,
Dial: sshClient.Dial, // ここで SSH Client を利用
TLSHandshakeTimeout: 10 * time.Second,
},
}
es, err := elasticsearch.NewClient(esConf)
if err != nil {
log.Fatal(err)
}
// ------------------------------
// リクエストを実行 (/_cat/indices)
// ------------------------------
req := esapi.CatIndicesRequest{
Format: "json",
Pretty: true,
}
ctx := context.Background()
resp, err := req.Do(ctx, es)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
// ------------------------------
// レスポンスを解析
// ------------------------------
if resp.IsError() {
log.Fatal(resp.String())
}
body := io.TeeReader(resp.Body, os.Stdout) // debug
var r []map[string]interface{}
if err := json.NewDecoder(body).Decode(&r); err != nil {
log.Fatal(err)
}
for i, obj := range r {
fmt.Printf("\n[#%d]\n", i)
for k, v := range obj {
fmt.Println(k, v)
}
}
}
Reference
이 문제에 관하여(【Go】 발판 서버 경유 (ssh) 로 VPC 엔드포인트의 Elasticsearch Service 에 로컬로부터 접속한다 【AWS】), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/rema424/items/37b42d6690a7dfe973e9
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
ssh -i <path/to/private-key> <username>@<hostname> curl -s '<ES_ENDPOINT>/_cat/indices?format=json&pretty'
package main
import (
"context"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"log"
"net"
"net/http"
"os"
"time"
"github.com/elastic/go-elasticsearch/v8"
"github.com/elastic/go-elasticsearch/v8/esapi"
"golang.org/x/crypto/ssh"
)
func main() {
log.SetFlags(log.LstdFlags | log.Lshortfile)
var (
sshUser = os.Getenv("SSH_USER")
sshHost = os.Getenv("SSH_HOST")
sshPort = os.Getenv("SSH_PORT")
sshPrivateKey = os.Getenv("SSH_PRIVATE_KEY")
esEndpoint = os.Getenv("ES_ENDPOINT")
)
// ------------------------------
// 秘密鍵ファイルの読み込み
// ------------------------------
b, err := ioutil.ReadFile(sshPrivateKey)
if err != nil {
log.Fatal(err)
}
signer, err := ssh.ParsePrivateKey(b)
if err != nil {
log.Fatal(err)
}
// ------------------------------
// SSH クライアントの生成
// ------------------------------
sshConf := ssh.ClientConfig{
User: sshUser,
Auth: []ssh.AuthMethod{
ssh.PublicKeys(signer),
},
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
return nil
},
Timeout: 10 * time.Second,
}
sshClient, err := ssh.Dial("tcp", net.JoinHostPort(sshHost, sshPort), &sshConf)
if err != nil {
log.Fatal(err)
}
defer sshClient.Close()
// ------------------------------
// Elasticsearch クライアントの生成
// ------------------------------
esConf := elasticsearch.Config{
Addresses: []string{esEndpoint},
Transport: &http.Transport{
Proxy: http.ProxyFromEnvironment,
Dial: sshClient.Dial, // ここで SSH Client を利用
TLSHandshakeTimeout: 10 * time.Second,
},
}
es, err := elasticsearch.NewClient(esConf)
if err != nil {
log.Fatal(err)
}
// ------------------------------
// リクエストを実行 (/_cat/indices)
// ------------------------------
req := esapi.CatIndicesRequest{
Format: "json",
Pretty: true,
}
ctx := context.Background()
resp, err := req.Do(ctx, es)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
// ------------------------------
// レスポンスを解析
// ------------------------------
if resp.IsError() {
log.Fatal(resp.String())
}
body := io.TeeReader(resp.Body, os.Stdout) // debug
var r []map[string]interface{}
if err := json.NewDecoder(body).Decode(&r); err != nil {
log.Fatal(err)
}
for i, obj := range r {
fmt.Printf("\n[#%d]\n", i)
for k, v := range obj {
fmt.Println(k, v)
}
}
}
Reference
이 문제에 관하여(【Go】 발판 서버 경유 (ssh) 로 VPC 엔드포인트의 Elasticsearch Service 에 로컬로부터 접속한다 【AWS】), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/rema424/items/37b42d6690a7dfe973e9텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)