Golang: генерация сертификатов с собственным корневым сертификатом для использования mTLS для работы микросервисов
Вот пошаговое руководство по генерации сертификатов с использованием собственного корневого сертификата (CA) для настройки mTLS между микросервисами.
1. Создание собственного корневого сертификата (CA)
Корневой сертификат будет использоваться для подписывания сертификатов сервера и клиента.
1 2 3 4 5 6 7 |
# Создаём приватный ключ для корневого сертификата openssl genrsa -out ca.key 4096 # Генерируем самоподписанный корневой сертификат openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 -out ca.crt \ -subj "/C=US/ST=State/L=City/O=Organization/OU=OrgUnit/CN=MyRootCA" |
ca.key
: закрытый ключ корневого сертификата.ca.crt
: самоподписанный корневой сертификат.
2. Генерация сертификата для сервиса (сервер)
- Создаём ключ и запрос на подпись (CSR) для сервера.
1234567# Создаём приватный ключ для сервераopenssl genrsa -out server.key 2048# Создаём запрос на подпись сертификата (CSR)openssl req -new -key server.key -out server.csr \-subj "/C=US/ST=State/L=City/O=Organization/OU=Server/CN=server.local"
1234# Создаём серверный сертификатopenssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \-out server.crt -days 365 -sha256
server.key
: приватный ключ сервера.server.csr
: запрос на подпись сертификата.server.crt
: подписанный сертификат сервера.
3. Генерация сертификата для клиента
- Создаём ключ и запрос на подпись (CSR) для клиента.
1234567# Создаём приватный ключ для клиентаopenssl genrsa -out client.key 2048# Создаём запрос на подпись сертификата (CSR)openssl req -new -key client.key -out client.csr \-subj "/C=US/ST=State/L=City/O=Organization/OU=Client/CN=client.local"
1234# Создаём клиентский сертификатopenssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial \-out client.crt -days 365 -sha256client.key
: приватный ключ клиента.client.csr
: запрос на подпись сертификата.client.crt
: подписанный сертификат клиента.
4. Настройка сервера для mTLS
Пример кода сервера на Go:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
package main import ( "crypto/tls" "crypto/x509" "io/ioutil" "log" "net" "google.golang.org/grpc" "google.golang.org/grpc/credentials" pb "path/to/your/protobufs" ) func main() { // Загрузка корневого сертификата caCert, err := ioutil.ReadFile("ca.crt") if err != nil { log.Fatalf("Не удалось загрузить CA сертификат: %v", err) } // Создание пула корневых сертификатов certPool := x509.NewCertPool() if !certPool.AppendCertsFromPEM(caCert) { log.Fatal("Не удалось добавить CA сертификат в пул") } // Загрузка сертификата сервера serverCert, err := tls.LoadX509KeyPair("server.crt", "server.key") if err != nil { log.Fatalf("Не удалось загрузить серверный сертификат: %v", err) } // Настройка TLS creds := credentials.NewTLS(&tls.Config{ Certificates: []tls.Certificate{serverCert}, ClientAuth: tls.RequireAndVerifyClientCert, ClientCAs: certPool, }) // Создание gRPC сервера grpcServer := grpc.NewServer(grpc.Creds(creds)) // Регистрация сервиса pb.RegisterYourServiceServer(grpcServer, &YourService{}) // Запуск сервера listener, err := net.Listen("tcp", ":50051") if err != nil { log.Fatalf("Не удалось запустить сервер: %v", err) } log.Println("Сервер запущен на порту 50051 с mTLS") if err := grpcServer.Serve(listener); err != nil { log.Fatalf("Ошибка работы сервера: %v", err) } } |
5. Настройка клиента для mTLS
Пример кода клиента на Go:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
package main import ( "context" "crypto/tls" "crypto/x509" "io/ioutil" "log" "time" "google.golang.org/grpc" "google.golang.org/grpc/credentials" pb "path/to/your/protobufs" ) func main() { // Загрузка корневого сертификата caCert, err := ioutil.ReadFile("ca.crt") if err != nil { log.Fatalf("Не удалось загрузить CA сертификат: %v", err) } // Создание пула корневых сертификатов certPool := x509.NewCertPool() if !certPool.AppendCertsFromPEM(caCert) { log.Fatal("Не удалось добавить CA сертификат в пул") } // Загрузка клиентского сертификата clientCert, err := tls.LoadX509KeyPair("client.crt", "client.key") if err != nil { log.Fatalf("Не удалось загрузить клиентский сертификат: %v", err) } // Настройка TLS creds := credentials.NewTLS(&tls.Config{ Certificates: []tls.Certificate{clientCert}, RootCAs: certPool, }) // Подключение к серверу conn, err := grpc.Dial("localhost:50051", grpc.WithTransportCredentials(creds)) if err != nil { log.Fatalf("Не удалось подключиться к серверу: %v", err) } defer conn.Close() client := pb.NewYourServiceClient(conn) // Вызов метода ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() resp, err := client.YourMethod(ctx, &pb.YourRequest{Param: "Пример"}) if err != nil { log.Fatalf("Ошибка вызова метода: %v", err) } log.Printf("Ответ от сервера: %s", resp.GetMessage()) } |
6. Проверка
- Запустите сервер.
- Запустите клиента.
- Проверьте, что соединение устанавливается только при наличии правильных сертификатов.
Полезные советы
- Для автоматизации генерации сертификатов используйте скрипты или инструменты вроде cfssl.
- В продакшене избегайте самоподписанных сертификатов — используйте внешние CA (например, HashiCorp Vault или Let’s Encrypt).